java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View .MainActivity.findViewById(int)' on a null object reference

I have a class called MainActivity.java that call an AsyncTask class. The last class have a findViewById() that in execution return this error:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View <mypackage>.MainActivity.findViewById(int)' on a null object reference

I don't understand how can I edit an ImageView positioned in R.layout.activity_main after that an AsyncTask finish to work.

MainActivity.java

public class MainActivity extends Activity {

    public MainActivity() {}

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Connection().execute();
    }

}

Connection.java

public class Connection extends AsyncTask<String, Void, String> {
    public String result;

    //I know, this isn't correct, how can i do?
    public MainActivity MainActivity;

    @Override
    protected String doInBackground(String... arg0) {
        // TODO Auto-generated method stub
                //...

        return "a string";
    }

    protected void onPostExecute(String result) {
        super.onPostExecute(result);
                    //...

            // Where the error is generated
            ImageView image = (ImageView) MainActivity.findViewById(R.id.image);

            //...

    }
}

Answers


The error is that

public MainActivity MainActivity;

is never initialized, thus pointing to null. To make your code work the minimum step is in MainActivity

new Connection(this).execute();

In Connection

public class Connection extends AsyncTask<String, Void, String> {

    public MainActivity MainActivity;

    public Connection(MainActivity activity) {
        MainActivity = activity;
    }

But creating a task in onCreate and passing an Activity is not the best idea anyway. Also, field names should always start with a lowercase letter.

The best way is passing an ImageView to the AsyncTask. Don't start a task until the Activity is started and also, don't forget to cancel the task when the Activity is stopped.

public final class MainActivity extends Activity {

    public MainActivity() {}

    private Connection connection;
    private ImageView imageView;

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

        imageView = (ImageView) findViewById(R.id.image);
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (connection == null || connection.getStatus() != AsyncTask.Status.RUNNING) {
            connection = new Connection(imageView);
            connection.execute();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (connection != null && connection.getStatus() == AsyncTask.Status.RUNNING) {
            connection.cancel(true);
        }
    }

}

In Connection.java, store an ImageView as a WeakReference to avoid leaks.

public final class Connection extends AsyncTask<String, Void, String> {

    private final WeakReference<ImageView> imageViewRef;

    public Connection(ImageView view) {
        imageViewRef = new WeakReference<ImageView>(view);
    }

    @Override
    protected String doInBackground(String... arg0) {
        // TODO Auto-generated method stub
                //...

        return "a string";
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
                //...

        final ImageView imageView = imageViewRef.get();
        // if the Activity is still alive, the ImageView will not be null
        if (imageView != null) {
            // set an image or whatever you need
            image.setImageResource(666);
        }

    }

put imageview as a variable of your class

private ImageView image;

on your onCreate initialize

image = (ImageView) findViewById(R.id.image);


public class Connection extends AsyncTask<String, Void, String> {
        public String result;

        //I know, this isn't correct, how can i do?
        public MainActivity MainActivity;

        @Override
        protected String doInBackground(String... arg0) {
        // TODO Auto-generated method stub
            //...

        return "a string";
    }

    protected void onPostExecute(String result) {
        super.onPostExecute(result);
                //...

        // Where the error is generated
        //do other stuff with your imageview

        //...

    }
}

You did not specify what parameter you pass to Connection.java AsyncTask.

One of my student is also having same problem. Although he is using Volley Library for HttpConnection (posting data) and main issue was: he is writing URL directly without the http protocol prefix i.e.

String post_url ="api/do_post";

Simply add http/https at front of your post url:

String post_url ="http://api/do_post";


actually i was working an activity and service application. same problem i also got, in that in bindservice i have used the BIND_IMPORTANT flag instead of using BIND_AUTO_CREATE.

once i changed the flag it was worked successfully for me.


Need Your Help

Python program to calculate harmonic series

python math

Does anyone know how to write a program in Python that will calculate the addition of the harmonic series. i.e. 1 + 1/2 +1/3 +1/4...

ASP.NET catch referenced script file exceptions

asp.net javascript exception

How to catch exceptions raised by a referenced javascript file in an aspx page??