为什么我的Android应用程序因NullPointerException而崩溃?

时间:2014-04-21 15:46:49

标签: java android eclipse nullpointerexception adt

META-EDIT#2:第二个想法,那就是我将要做的事情,因为嘲笑我会问一个问题,如果我确实提出了一个新的问题,那么最终会遇到与此问题截然不同的问题。 / p> META-EDIT:这个问题变得越来越长,没有答案,并且在某个方面有所改变(到了我会问一个不同的问题,如果从头开始重写它,尽管它仍然是相同的问题)。我应该继续更新吗,还是应该提出新问题?我是新来的,所以我不知道标准礼仪是什么。

我正在构建一个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;
    }
}

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对象,您可能还需要进行更改。