Android app force closes - setOnClickListener [sim

2019-09-20 18:12发布

问题:

Program functions as normal on start up. As soon as button is clicked, app force closes and the log cat (at bottom) is shown.

XML File - layout is fully functional

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.figurehowtodo.MainActivity$PlaceholderFragment" >

<TextView
    android:id="@+id/produceText1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />

<Button
    android:id="@+id/myactualbutton"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="ClickMe" />

</LinearLayout>

MainActivity.java

package com.example.figurehowtodo;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {

    Button mybutton;
    TextView tvView;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_main);
        mybutton = (Button) findViewById(R.id.myactualbutton);
        tvView = (TextView) findViewById(R.id.produceText1);
        mybutton.setOnClickListener(new MyOwnOnClickListener());
    }

}

MyOwnOnClickListener.java

package com.example.figurehowtodo;

import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;

public class MyOwnOnClickListener extends Activity implements OnClickListener{
    //int id;
    TextView id2;
    //TextView id3;

    /* MainActivity caller;
    public MyOwnOnClickListener() {
        addiTion();
        IGNORE THIS BIT
    } */

    public void onClick(View v) {
        addiTion(v);
    }

    public void addiTion(View v){
        //id = hello.getId();
        id2 = (TextView) findViewById(R.id.produceText1);
        id2.setText("fgdsgdfhgdfh");
    }
}

Logcat:

03-27 20:56:31.710: E/AndroidRuntime(2132): FATAL EXCEPTION: main
03-27 20:56:31.710: E/AndroidRuntime(2132): java.lang.NullPointerException
03-27 20:56:31.710: E/AndroidRuntime(2132):     at android.app.Activity.findViewById(Activity.java:1647)
03-27 20:56:31.710: E/AndroidRuntime(2132):     at com.example.figurehowtodo.MyOwnOnClickListener.addiTion(MyOwnOnClickListener.java:29)
03-27 20:56:31.710: E/AndroidRuntime(2132):     at com.example.figurehowtodo.MyOwnOnClickListener.onClick(MyOwnOnClickListener.java:22)
03-27 20:56:31.710: E/AndroidRuntime(2132):     at android.view.View.performClick(View.java:2485)
03-27 20:56:31.710: E/AndroidRuntime(2132):     at android.view.View$PerformClick.run(View.java:9080)
03-27 20:56:31.710: E/AndroidRuntime(2132):     at android.os.Handler.handleCallback(Handler.java:587)
03-27 20:56:31.710: E/AndroidRuntime(2132):     at android.os.Handler.dispatchMessage(Handler.java:92)
03-27 20:56:31.710: E/AndroidRuntime(2132):     at android.os.Looper.loop(Looper.java:123)
03-27 20:56:31.710: E/AndroidRuntime(2132):     at android.app.ActivityThread.main(ActivityThread.java:3683)
03-27 20:56:31.710: E/AndroidRuntime(2132):     at java.lang.reflect.Method.invokeNative(Native Method)
03-27 20:56:31.710: E/AndroidRuntime(2132):     at java.lang.reflect.Method.invoke(Method.java:507)
03-27 20:56:31.710: E/AndroidRuntime(2132):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
03-27 20:56:31.710: E/AndroidRuntime(2132):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
03-27 20:56:31.710: E/AndroidRuntime(2132):     at dalvik.system.NativeStart.main(Native Method)
03-27 20:56:31.720: W/ActivityManager(61):   Force finishing activity com.example.figurehowtodo/.MainActivity
03-27 20:56:32.230: W/ActivityManager(61): Activity pause timeout for HistoryRecord{40698748 com.example.figurehowtodo/.MainActivity}
03-27 20:56:38.440: D/dalvikvm(299): GC_EXPLICIT freed 6K, 54% free 2544K/5511K, external 1625K/2137K, paused 55ms
03-27 20:56:43.380: W/ActivityManager(61): Activity destroy timeout for HistoryRecord{40698748 com.example.figurehowtodo/.MainActivity}
03-27 20:56:43.480: D/dalvikvm(311): GC_EXPLICIT freed 2K, 54% free 2537K/5511K, external 1625K/2137K, paused 78ms
03-27 20:56:48.460: D/dalvikvm(220): GC_EXPLICIT freed 184K, 54% free 2764K/5959K, external 2202K/2671K, paused 56ms

回答1:

You have not set you content view for your activity class MyOwnOnClickListener. So method findViewById() cannot find the view you are passing as argument.

I think the MyOwnOnClickListener class shouldn't be an Activity class, but just a listener. You can pass a reference to the TextView to the listener to use it.

Or you can implement the listener in your MainActivity class and suppress the MyOwnOnClickListener class.

public class MainActivity extends Activity implements OnClickListener {
    Button mybutton;
    TextView tvView;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_main);
        mybutton = (Button) findViewById(R.id.myactualbutton);
        tvView = (TextView) findViewById(R.id.produceText1);
        mybutton.setOnClickListener(this);
    }

    public void onClick(View v) {
        addiTion(v);
    }

    public void addiTion(View v){
        tvView.setText("fgdsgdfhgdfh");
    }
}

EDIT: If you want to use a listener class, just keep your MainActivity as it is, change only the call to the MyOwnOnClickListener to pass the tvView reference, and change the MyOwnOnClickListener class like this:

public class MyOwnOnClickListener implements OnClickListener{
TextView id2;

    // MainActivity caller;
    public MyOwnOnClickListener(TextView id2) {
        this.id2 = id2;
    }

    public void onClick(View v) {
        switch(v.getId()) {
        case R.id.produceText1:
            id2.setText("fgdsgdfhgdfh");
            break;
        // Other cases here...
        default:
            // Whatever you want to manage the situation...
        }
    }
}

It should work...



回答2:

replace your

mybutton.setOnClickListener(new MyOwnOnClickListener());

by

mybutton.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
         tvView.setText("fgdsgdfhgdfh");
    }   
});

which is called anonymous class in Java.

Setting listener this way, you declare anonymous class that implements interface OnClickListener, implement its abstract method onClick , create an object of this anonymous class and pass this object onto button's setOnClickListener method to make your button proceed clicks on it in a way you want.



回答3:

Alternative Solution with onClick attribute:

Add this attribute to your Button in the xml:

android:onClick="buttonClicked"

and add this method to the MainActivity:

public void buttonClicked(View view) {
     tvView.setText("fgdsgdfhgdfh");
}

then also delete this line:

mybutton.setOnClickListener(new MyOwnOnClickListener());

then get rid of the whole MyOwnOnClickListener Activity at all