获得NPE(已编辑)

时间:2013-03-24 08:06:05

标签: java android nullpointerexception runtime

我还在接受NPE,但现在它来自我的onCreate()。当我删除按钮时,一切正常。

以下是XML(每个表行来自不同的XML):

<TableRow
        android:id="@+id/tableRow1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp" >

        <Button
            android:id="@+id/doneP1"
            android:layout_width="50dp"
            android:layout_height="wrap_content"
            android:text="Done" />

        <Button
            android:id="@+id/resetP1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Reset" />

    </TableRow>

<TableRow
            android:id="@+id/tableRow1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp" >

            <Button
                android:id="@+id/doneP2"
                android:layout_width="50dp"
                android:layout_height="wrap_content"
                android:text="Done" />

            <Button
                android:id="@+id/resetP2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Reset" />

        </TableRow>

以下是代码:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tictactoegame);

        /*doneP1 = (Button) this.findViewById(R.id.doneP1);
        doneP2 = (Button) this.findViewById(R.id.doneP2);
        resetP1 = (Button) this.findViewById(R.id.resetP1);
        resetP2 = (Button) this.findViewById(R.id.resetP2);

        checkTurn(); //starts the game

        //buttons
        doneP1.setOnClickListener(this);
        doneP2.setOnClickListener(this);
        resetP1.setOnClickListener(this);
        resetP2.setOnClickListener(this);*/ //commented out 
    }

在onCreate之外

@Override
public void onClick(View v) {
       switch(v.getId()) {
       case R.id.doneP1:
            checkTurn();
           break;
       case R.id.doneP2:
           checkTurn();
           break;
       case R.id.resetP1:
           break;
       case R.id.resetP2:
           break;
       }
}

这是检查结果

public void checkTurn()
    {
        if(turn == 1)
        {
            changeLayout(turn);
            turn = 2;
        }
        else
        {
            changeLayout(turn);
            turn = 1;
        }
    }

这里是changelayout(编辑:new changeLayout,我只是重新初始化了方法中的每个按钮,但仍然没有效果,我做得对吗?)

public void changeLayout(int turn)
{
    FragmentManager fm       = getSupportFragmentManager();
    Fragment        fragment = fm.findFragmentById(R.id.fragment_container);
    FragmentTransaction ft;

    if(turn == 1) //if its player 1's turn
    {  
        doneP1 = (Button) this.findViewById(R.id.doneP1);
        resetP1 = (Button) this.findViewById(R.id.resetP1);
        doneP1.setOnClickListener(this);
        resetP1.setOnClickListener(this);
        if(fragment == null) //checks wether the current framelayout contains a fragment or not
        {   
            ft = fm.beginTransaction();
            ft.add(R.id.fragment_container, new PlayerTurn1());
            ft.commit(); 
            //setPlayer1();
        }
        else
        {
            ft = fm.beginTransaction();
            ft.replace(R.id.fragment_container, new PlayerTurn1());
            ft.commit();

        }
    }
    else
    {   
        doneP2 = (Button) this.findViewById(R.id.doneP2); 
        resetP2 = (Button) this.findViewById(R.id.resetP2);  
        doneP2.setOnClickListener(this);
        resetP2.setOnClickListener(this);
        if(fragment == null)
        {
            ft = fm.beginTransaction();;
            ft.add(R.id.fragment_container, new PlayerTurn2());
            ft.commit(); 
            //setPlayer2();
        }
        else
        {
            ft = fm.beginTransaction();;
            ft.replace(R.id.fragment_container, new PlayerTurn2());
            ft.commit(); 
        }
    }
}

这里是logcat

  

03-24 07:51:55.954:E / AndroidRuntime(5092):引起:   java.lang.NullPointerException 03-24 07:51:55.954:   E / AndroidRuntime(5092):at   As2.packageTK.TicTacToeGame.onCreate(TicTacToeGame.java:88)

第88行是:

doneP1.setOnClickListener(this);

我现在已经工作了大约4个小时,我仍然无法解决一个简单的问题。我的脑袋流口水,我真的很累,我想在睡觉前解决这个问题,所以我会很感激你的快速反应。我清理并重建了我的问题......没事。一切似乎都很好,但没有...... NPE总是要陷入其中。

2 个答案:

答案 0 :(得分:0)

如果您在

上获得NPE
doneP1.setOnClickListener(this);

这意味着doneP1为null。您是否通过打印/登录doneP1,doneP2,resetP1和resetP2(当然是第88行之前)进行了检查。例如:

Log.d(TAG, "doneP1 = "+doneP1);
Log.d(TAG, "doneP2 = "+doneP2);
...

我的猜测是所有这些组件都是null。这意味着您可能正在加载错误的布局。或者也许你从一开始就加载了正确的一个,但你在

中更改了其他内容
public void changeLayout(int turn)

修改

你的TableRows有不同的布局吗?

"Here are the XML(each table rows are from separate XMLs):"

当然,加载P2布局时P1组件将为null,反之亦然。

<强> EDIT2:

在changeLayout中加载您的引用。由于您在屏幕上同时只有两个按钮(重置和完成),您实际上只需要两个引用(即您不需要donep1和donep2)。然后在更改布局中,将引用更改为正确的按钮。因此,你需要依次点击按钮的逻辑。

答案 1 :(得分:0)

看起来你正在onCreate中获得这些观点:

  doneP1 = (Button) this.findViewById(R.id.doneP1);
    doneP2 = (Button) this.findViewById(R.id.doneP2);
    resetP1 = (Button) this.findViewById(R.id.resetP1);
    resetP2 = (Button) this.findViewById(R.id.resetP2);

但在您更改为转身并更改了以下内容的布局后

public void checkTurn()
{
    if(turn == 1)
    {
        changeLayout(turn);
        turn = 2;
    }
    else
    {
        changeLayout(turn);
        turn = 1;
    }
}

并运行此:

ft.replace(R.id.fragment_container, new PlayerTurn1());

你基本上失去了对这些观点的引用。因为现在不存在了。他们被另一个片段的观点所取代。

修改

替代方案是在布局文件中设置onClick属性:

设置"android:onClick="onDoneButtonOnClick"

并在您的活动中创建方法:

public void onDoneButtonOnClick (View v)
{
      // do here what every you want with this button.
}

在这种情况下,您必须从活动中删除onClickListener的实施。