1

我仍在获得 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;
       }
}

这是checkturn

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

这是changelayout(编辑:新的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): 在 As2.packageTK.TicTacToeGame.onCreate(TicTacToeGame .java:88)

第 88 行是:

doneP1.setOnClickListener(this);

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

4

2 回答 2

0

如果你得到一个 NPE

doneP1.setOnClickListener(this);

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

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

我的猜测是所有这些组件都是空的。这意味着您可能加载了错误的布局。或者,也许您从一开始就加载了正确的内容,但您将其更改为其他内容

public void changeLayout(int turn)

编辑:

您的 TableRows 有不同的布局?

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

那么当你加载 P2 布局时,当然 P1 组件将为空,反之亦然。

编辑2:

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

于 2013-03-24T08:18:42.080 回答
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从您的活动中删除实现。

于 2013-03-24T08:26:18.057 回答