[英]Why is my Android application crashing with a NullPointerException?
META-EDIT #2: On second thought, that's what I will do, as mocking up the question I would ask if I did make a new question ended up with a far different question from this one. META-EDIT#2:第二个想法就是我要做的,因为我要问一个问题,即我是否提出了一个新问题,结果却与此问题截然不同。
META-EDIT: This question is getting quite long, does not have an answer, and has shifted in topic somewhat (to the point where I would ask a much different question if rewriting it from scratch, despite it still being the same problem ). META-EDIT:这个问题已经很长了,没有答案,并且话题有所改变(以至于我要问一个从头开始重写的问题,尽管它仍然是同样的问题 ,但我会提出一个截然不同的问题 )。 Should I continue to update it, or should I make a new question? 我应该继续更新它还是要提出一个新问题? I'm new here, so I don't know what the standard etiquette is for this. 我是新来的,所以我不知道这是什么标准礼节。
I am building an Android application that will allow the user to navigate a campus by inputting the number of the room they are currently in and the number of the room which they wish to get to. 我正在构建一个Android应用程序,该应用程序将允许用户输入当前所在房间的数量和希望进入的房间的数量来浏览校园。 I think I am nearly finished, but (despite several weeks of fruitless work) I have been unable to fix one particular bug, which causes the program to crash with: 我想我快要完成了,但是(尽管工作了几周徒劳无功),但我无法修复一个特定的错误,该错误导致程序崩溃:
java.lang.IllegalStateException: Could not execute method of the activity
at android.view.View$1.onClick(View.java:3633)
at android.view.View.performClick(View.java:4240)
at android.view.View$PerformClick.run(View.java:17721)
at android.on.Handler.handleCallback(Handler.java:730)
at android.on.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Mathod.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.reflect.InvokationTargetExeption
at java.lang.reflect.Method.invokeNative(Native Method)
at Java.lang.reflect.Method.invoke(Method.java:525)
at android.view.View$1.onClick(View.java:3628)
... 11 more
Caused by: java.lang.NullPointerException
at ghamas.navigator.WorldMap.makePath(WorldMap.java:669)
at ghamas.navigator.MainActivity.makeRoute(MainActivity.java:81)
at ghamas.navigator.MainActivity.callMakeRoute(MainActivity.java:61)
... 14 more
WorldMap.makePath(): WorldMap.makePath():
ArrayList<Coordinates> makePath(Coordinates startNode, Coordinates endNode, ArrayList<Coordinates> pathSoFar, ArrayList<Coordinates> closedNodes, ArrayList<Coordinates> openNodes)
{ //recursively finds the path from startNode to endNode:
//start @ starting node, make list of ways out of it
//for each of these potential paths, find all the potential paths out of them
//and so on until these paths reach the end
//as the recursion collapses, the best paths are passed back up, and the others discarded
//this ensures that the path returned by the last call of the method is the best one
//this method is very, very inefficient, but is very simple
//mainly, however, since the map has a very tiny number of potential paths, relatively speaking, the inefficiency is acceptable
//if first call (just starting)
if (openNodes.size() == 0 && !closedNodes.contains(startNode)) { openNodes.add(startNode); }
int a = startNode.z; //traced NullPointerException back to here
Coordinates n = openNodes.get(0); //get a node to test
openNodes.remove(0); //remove it from the open nodes, so don't repeat it later
closedNodes.add(n); //record that have done this one
ArrayList<Coordinates> adjacent = getAdjacentCoords(n);
//get the nodes that are adjacent to this one
for (int i = 0; i < adjacent.size(); i++)
{
//if this adjacent node has not yet been checked - this prevents infinite loops
if (!openNodes.contains(adjacent.get(i)) && !closedNodes.contains(adjacent.get(i)))
{ //add it to the list of nodes to check
openNodes.add(adjacent.get(i));
}
}
//if reached destination
if (n == endNode)
{ //done
pathSoFar.add(n);
return pathSoFar;
}
else
{
ArrayList<ArrayList<Coordinates>> pathList = new ArrayList<ArrayList<Coordinates>>(); //list of potential paths that come from this node + path
// openNodes = coordOrder(openNodes, endNode); //don't need this (right now, at least), as dealing with a tiny number of nodes
for (int i = 0; i < openNodes.size(); i++)
{ //recursively add the paths - should be max. 3 - inward path + four other directions, but only ever put max 3 in the map
pathList.add(makePath(startNode, endNode, pathSoFar, closedNodes, openNodes));
}
int lowVal = 1024; //length of beth path from here to end
int iLow = -1; //index of the best path from here to end
//check all paths found just before
for (int i = 0; i < pathList.size(); i++)
{ //if this path is smaller than the previous smallest found one, this is the new smallest found one
if (pathList.get(i).size() < lowVal) { iLow = i; lowVal = pathList.get(i).size(); i = 0; }
}
//return the best path to proceed from this node to the end
return pathList.get(iLow);
}
}
MainActivity.makeRoute(): MainActivity.makeRoute():
public ArrayList<Coordinates> makeRoute(String start, String end)
{
destination = end;
ArrayList<Coordinates> newCoordArr = new ArrayList<Coordinates>();
ArrayList<Coordinates> path = world.makePath(world.findCoordsWithRoom(start), world.findCoordsWithRoom(end), newCoordArr, newCoordArr, newCoordArr);
return path;
}
MainActivity.callMakeRoute(): MainActivity.callMakeRoute():
public void callMakeRoute (View view)
{ //function called when button in UI tab is pressed
String startstr = ((EditText)pagerAdapter.getItem(0).getView().findViewById(R.id.starting_room_field)).getText().toString();
String endstr = ((EditText)pagerAdapter.getItem(0).getView().findViewById(R.id.ending_room_field)).getText().toString();
ArrayList<String> newTextArr = instruct(makeRoute(startstr, endstr)); //get the route
String newText = ""; //move the newTextArr to a single string
Integer i = 0;
//translate route to format the textview tab can handle
//that is, a single line, with newline characters between instructions
for (String s : newTextArr)
{
newText.concat(i.toString() + ") "); //the number of the step, i.e. 1) ... 2) ... 3) ... etc.
newText.concat(s); //the step text itself, e.g. "Turn left...", "Continue forwards", etc.
newText.concat("\n\n"); //skip a line between steps
i++; //next step
}
//push the new text to the text tab's TextView
((TextView)(pagerAdapter.getItem(1).getView().findViewById(R.id.text_view_text_spot))).setText(newText);
}
The Coordinates class holds the integers x, y, and z. Coordinates类包含整数x,y和z。
This is a component of the WorldMap class: 这是WorldMap类的组件:
Node[][][] map =
{
{ //first floor
//00 01 02 03 04 05 06 07 08 09
{dne, dne, dne, dne, dne, cls, dne, dne, dne, dne}, //00
{dne, dne, dne, dne, oc, cl, cf, dne, dne, dne}, //01
{dne, dne, dne, dne, dne, dne, dne, dne, dne, dne}, //02
{dne, dne, dne, dne, og2, g4, gc, g2, gs1, dne}, //03
{dne, dne, dne, dne, dne, dne, gs2, g1, g3, dne}, //04
{dne, ot3, dne, ot1, op, dne, og1, gal, dne, dne}, //05
{dne, ot4, dne, dne, dne, dne, a2, a1, dne, dne}, //06
{dne, t3, dne, dne, dne, dne, dne, a3, as, dne}, //07
{dne, t1, tl1, ot2, dne, dne, dne, a4, dne, dne}, //08
{ ts, t2, tl2, ot5, dne, dne, dne, dne, dne, dne}, //09
{dne, t4, tls, dne, dne, dne, dne, dne, dne, dne}, //10
},
{ //second floor
//00 01 02 03 04 05 06 07 08 09
{dne, dne, dne, dne, dne, CLS, dne, dne, dne, dne}, //00
{dne, dne, dne, dne, dne, CL, C2, C4, dne, dne}, //01
{dne, dne, dne, dne, dne, C1, C3, C5, dne, dne}, //02
{dne, dne, dne, dne, dne, G4, GC1, G3, GS1, dne}, //03
{dne, dne, dne, dne, dne, GC2, dne, G1, G2, dne}, //04
{dne, dne, dne, dne, dne, GS2, dne, GAL, dne, dne}, //05
{dne, dne, dne, dne, dne, dne, A5,GALS, dne, dne}, //06
{dne, dne, dne, dne, dne, dne, A3, A1, dne, dne}, //07
{dne, dne, dne, dne, dne, dne, dne, A2, AS, dne}, //08
{ TS, T4, T3, dne, dne, dne, dne, dne, dne, dne}, //09
{dne, TLS, TL, dne, dne, dne, dne, dne, dne, dne}, //10
}
};
All of the components of the array are defined like this: 数组的所有组件的定义如下:
Node ot1 = new Node(
new ConnectionTo[] {
new ConnectionTo(new Node(new Coordinates()), new Room[]{}, Direction.north),
new ConnectionTo(new Node(new Coordinates(0,5,4)), new Room[]{}, Direction.east),
new ConnectionTo(new Node(new Coordinates(0,8,3)), new Room[]{}, Direction.south),
new ConnectionTo(new Node(new Coordinates(0,5,1)), new Room[]{}, Direction.west),
new ConnectionTo(new Node(new Coordinates()), new Room[]{}, Direction.up),
new ConnectionTo(new Node(new Coordinates()), new Room[]{}, Direction.down)
}, new Coordinates(0,5,3)
);
There is a considerable amount of code that I did not include here in the interest of brevity, so if I overlooked something that is needed, please tell me so I can fix it. 为了简洁起见,这里没有包含大量代码,因此,如果我忽略了所需的内容,请告诉我,以便对其进行修复。
I am building for Android 4.3 using ADT v22.2.1-833290 as my IDE, the included emulator for my testing environment, and LogCat for debugging. 我正在使用ADT v22.2.1-833290作为IDE,用于测试环境的随附仿真器以及用于调试的LogCat为Android 4.3进行构建。
EDIT#01: The lines referenced above are: MainActivity.java:61 EDIT#01:上面引用的行是:MainActivity.java:61
ArrayList<String> newTextArr = instruct(makeRoute(startstr, endstr)); //get the route
MainActivity.java:81 MainActivity.java:81
ArrayList<Coordinates> path = world.makePath(world.findCoordsWithRoom(start), world.findCoordsWithRoom(end), newCoordArr, newCoordArr, newCoordArr);
WorldMap.java:669 WorldMap.java:669
int a = startNode.z; //traced NullPointerException back to here
Edit #02: WorldMap.findCoordswithRoom(): 编辑#02:WorldMap.findCoordswithRoom():
Coordinates findCoordsWithRoom(String roomName)
{
//all floors; 0 -> 1
for (int z = 0; z < map.length; z++)
{
//all rows; 0 -> 10
for (int y = 0; y < map[z].length; y++)
{
//all cols; 0 -> 9
for (int x = 0; x < map[z][y].length; x++)
{
if (map[z][y][x] == dne) { continue; } //if this node is a "dne" node, skip it
//all valid connections out of this node
for (int c = 0; c < map[z][y][x].dirArr.length; c++)
{
if (!map[z][y][x].dirArr[c].exists) { continue; }
//all rooms on this connection
for (int r = 0; r < map[z][y][x].dirArr[c].rooms.length; r++)
{
//if this room has the right name
if (map[z][y][x].dirArr[c].rooms[r].name.equals(roomName))
{ //found it
return (new Coordinates(x, y, z));
}
}
}
}
}
}
//failed to find it
return null;
}
EDIT #03: I've been working on this a bit more, and while I am still getting the same error, I have hit a bit of a breakthrough - the issue appears to be that the data that ends up in the Nodes declared in WorldMap is not the data included in the Nodes' declarations - rather, the Nodes end up with all fields either at their default values or with a value of null. 编辑#03:我已经做了更多的工作,虽然我仍然遇到相同的错误,但我取得了一些突破-问题似乎是数据最终在声明为Nodes中WorldMap不是节点声明中包含的数据-而是,节点最终以所有字段为默认值或值为null结束。 Here is an example of a Node declaration: 这是Node声明的示例:
Node g2 = new Node(
new ConnectionTo[] {
new ConnectionTo(new Node(new Coordinates()), new Room[]{}, Direction.north),
new ConnectionTo(new Node(new Coordinates(0,3,8)), new Room[]{}, Direction.east),
new ConnectionTo(new Node(new Coordinates(0,4,7)), new Room[]{}, Direction.south),
new ConnectionTo(new Node(new Coordinates(0,3,6)), new Room[]{new Room("104",new String[]{"left","right"}),new Room("120",new String[]{"right","left"})}, Direction.west),
new ConnectionTo(new Node(new Coordinates()), new Room[]{}, Direction.up),
new ConnectionTo(new Node(new Coordinates()), new Room[]{}, Direction.down)
}, new Coordinates(0,3,7)
);
And here are the relevant classes and constructors: 以下是相关的类和构造函数:
Node: 节点:
public class Node
{
ConnectionTo n, e, s, w, u, d;
ConnectionTo[] dirArr;
boolean[] hasConnection;
Coordinates coords;
boolean exists;
Coordinates targetCoordsHolder;
Node (ConnectionTo[] connections, Coordinates location)
{
hasConnection = new boolean[6];
exists = true;
n = connections[0];
e = connections[1];
s = connections[2];
w = connections[3];
u = connections[4];
d = connections[5];
dirArr = connections;
coords = location;
for (int i = 0; i < dirArr.length; i++)
{
hasConnection[i] = false;
if (dirArr[i].exists) { hasConnection[i] = true; }
}
if (location.equals(new Coordinates()))
{
exists = false;
}
}
}
ConnectionTo: 连接到:
public class ConnectionTo
{
Direction dir;
Room[] rooms;
Node targetNode;
boolean exists = true;
double cost;
public ConnectionTo (Node target, Room[] rms, Direction pdir, double cost)
{
if (target.coords.equals(new Coordinates()));
if (!target.exists)
{
exists = false;
return;
}
targetNode = target;
rooms = rms;
dir = pdir;
this.cost = cost;
}
public ConnectionTo() { exists = false; }
public ConnectionTo (Direction pdir)
{
this(new Node(), new Room[]{}, pdir, 256);
}
public ConnectionTo (Node target, Room[] rms, Direction pdir)
{
this (target, rms, pdir, 256);
}
}
Room: 房间:
public class Room
{
String name;
int num;
boolean nonstandardMsg;
String[] msgs;
Room (String roomName, int roomNum, String[] approachMsgs)
{
this(roomName, roomNum, approachMsgs, false);
}
Room (String roomName, int roomNum, String[] approachMsgs, boolean nsp)
{
name = roomName;
num = roomNum;
msgs = approachMsgs;
nonstandardMsg = nsp;
}
Room (String roomName, String[] approachMsgs)
{
this(roomName, approachMsgs, false);
}
Room (String roomName, String[] approachMsgs, boolean nsp)
{
name = roomName;
//if first character is a number
if (roomName.charAt(0) == '1' || roomName.charAt(0) == '2' || roomName.charAt(0) == '3' || roomName.charAt(0) == '4' || roomName.charAt(0) == '5' || roomName.charAt(0) == '6' || roomName.charAt(0) == '7' || roomName.charAt(0) == '8' || roomName.charAt(0) == '9' || roomName.charAt(0) == '0')
{
//if last character is number
if (roomName.charAt(roomName.length()-1) == '1' || roomName.charAt(roomName.length()-1) == '2' || roomName.charAt(roomName.length()-1) == '3' || roomName.charAt(roomName.length()-1) == '4' || roomName.charAt(roomName.length()-1) == '5' || roomName.charAt(roomName.length()-1) == '6' || roomName.charAt(roomName.length()-1) == '7' || roomName.charAt(roomName.length()-1) == '8' || roomName.charAt(roomName.length()-1) == '9' || roomName.charAt(roomName.length()-1) == '0')
{
num = Integer.parseInt(roomName);
}
else
{
num = Integer.parseInt(roomName.substring(0, roomName.length() - 2));
}
}
else
{
num = Integer.parseInt(roomName.substring(1));
}
msgs = approachMsgs;
nonstandardMsg = nsp;
}
}
Coordinates: 座标:
public class Coordinates
{
int x, y, z;
public Coordinates (int zp, int yp, int xp)
{
x = xp;
y = yp;
z = zp;
}
public Coordinates ()
{
x = -1;
y = -1;
z = -1;
}
}
The findCoordsWithRoom is returning null by the looks of it for your start value. findCoordsWithRoom会根据您的起始值返回null。
map[z][y][x].dirArr[c].rooms[r].name == roomName
That code will not return true. 该代码将不会返回true。 You want to replace it with 您要替换为
roomName.equals(map[z][y][x].dirArr[c].rooms[r].name)
Strings should be compared with .equals and not ==. 字符串应与.equals而不是==进行比较。 Also depending on what your dne object is you might need to make that change as well. 另外,根据您的dne对象是什么,您可能还需要进行更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.