我正在构建一个Android应用程序,允许用户通过输入他们当前所在房间的数量以及他们希望到达的房间的数量来导航校园。我想我差不多完成了,但是(尽管有几个星期没有结果的工作)我一直无法修复一个特定的错误,导致程序崩溃:
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():
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():
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():
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);
}
Coordinates类包含整数x,y和z。
这是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
}
};
数组的所有组件都是这样定义的:
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)
);
为了简洁起见,我在这里没有包含大量的代码,所以如果我忽略了需要的东西,请告诉我,我可以解决它。
我正在使用ADT v22.2.1-833290作为我的IDE,我的测试环境包含的模拟器和用于调试的LogCat构建Android 4.3。
编辑#01:上面引用的行是: MainActivity.java:61
ArrayList<String> newTextArr = instruct(makeRoute(startstr, endstr)); //get the route
MainActivity.java:81
ArrayList<Coordinates> path = world.makePath(world.findCoordsWithRoom(start), world.findCoordsWithRoom(end), newCoordArr, newCoordArr, newCoordArr);
WorldMap.java:669
int a = startNode.z; //traced NullPointerException back to here
编辑#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;
}
编辑#03:我已经开始研究这个问题,虽然我仍然遇到同样的错误,但 有点突破 - 问题似乎出现了因为在WorldMap中声明的节点中结束的数据不是节点中包含的数据。声明 - 相反,节点最终会将所有字段设置为默认值或值为null。以下是节点声明的示例:
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)
);
以下是相关的类和构造函数:
节点:
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);
}
}
间:
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;
}
}
坐标:
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;
}
}
答案 0 :(得分:2)
findCoordsWithRoom通过它的起始值返回null作为起始值。
map[z][y][x].dirArr[c].rooms[r].name == roomName
该代码不会返回true。您想用
替换它roomName.equals(map[z][y][x].dirArr[c].rooms[r].name)
字符串应与.equals进行比较,而不是==。同样取决于您的dne对象,您可能还需要进行更改。