繁体   English   中英

获取NPE(已编辑)

[英]Getting NPE (Edited)

我仍在获取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):在As2.packageTK.TicTacToeGame.onCreate(TicTacToeGame .java:88)

第88行是:

doneP1.setOnClickListener(this);

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

如果您获得了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上轮到谁的逻辑。

看起来您正在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的实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM