web-dev-qa-db-fra.com

java.lang.NullPointerException: tentative d'appeler la méthode virtuelle 'Android.view.View .MainActivity.findViewById (int)' sur une référence d'objet null

J'ai une classe appelée MainActivity.Java qui appelle une classe AsyncTask. La dernière classe a une findViewById() qui, en exécution, renvoie cette erreur:

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

Je ne comprends pas comment éditer une ImageView positionnée dans R.layout.activity_main après que AsyncTask a fini de fonctionner.

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);

            //...

    }
}
10
Kaos

L'erreur est que

public MainActivity MainActivity;

n’est jamais initialisé, pointant ainsi vers null . Pour que votre code fonctionne, l’étape minimale estin MainActivity

new Connection(this).execute();

En connection

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

    public MainActivity MainActivity;

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

Mais créer une tâche dans onCreate et passer une activité ne sont de toute façon pas la meilleure idée… .. De plus, les noms de champs doivent toujours commencer par une lettre minuscule.

La meilleure façon de passer un ImageView à la AsyncTask . Ne commencez pas une tâche tant que l'activité n'a pas démarrée et n'oubliez pas d'annuler la tâche lorsque l'activité est arrêtée.

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);
        }
    }

}

Dans Connection.Java, enregistrez un ImageView en tant que référence faible pour éviter les fuites.

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);
        }

    }
8
Yaroslav Mytkalyk

Vous n'avez pas spécifié le paramètre que vous transmettez à Connection.Java AsyncTask.

Un de mes étudiants a également le même problème. Bien qu'il utilise Volley Library pour HttpConnection (enregistrement de données) et que le problème principal était: Il écrit URL directement sans le préfixe http protocol i.e.

String post_url ="api/do_post";

Ajoutez simplement http/https au début de votre URL de publication:

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

0
silwalprabin

mettre imageview comme une variable de votre classe

private ImageView image;

sur votre initialisation onCreate

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

        //...

    }
}
0
Lucian Novac

en fait je travaillais une application d'activité et de service. Le même problème que j'ai aussi eu.

une fois que j'ai changé le drapeau, cela a fonctionné avec succès pour moi.

0
amit pandya