简体   繁体   中英

Using Threads in an Android app

In my android app, I have one Activity and more java class which is not an activity. So there is a get method in this other java class, which returns an Object. This method starts a new thread to gets the data and attaches it with the object

Now I am calling this get method in my Activity to get that object. I am doing something like this -

mNewsList = new ArrayList<NewsContentManager.NewsPojo>();
mNewsList = manager.getNewsList();

and the method is this -

    public ArrayList<NewsPojo> getNewsList() {
        Log.v("TAG", ""+newsList);
        if(newsList == null)
        {
            Thread t = new Thread(){
                public void run(){

                    Log.v("TAG", "Inside run");

                    np1 = new NewsPojo();
                    np1.setTitle("A");
                    np1.setDescription("dhghfdklsa");


                    np2 = new NewsPojo();
                    np2.setTitle("B");
                    np2.setDescription("dhghfdklsa");


                    np3 = new NewsPojo();
                    np3.setTitle("c");
                    np3.setDescription("dhghfdklsa");

                    newsList = new ArrayList<NewsPojo>();

                    Log.v("in run",""+newsList);

                    newsList.add(np1);
                    newsList.add(np2);
                    newsList.add(np3);

                    Log.v("in run",""+newsList.size());

                    setNewsList(newsList);

                    handler.sendEmptyMessage(0);

                }// end of run
            };// end of thread
            t.start();
        }//end of if

        return newsList;
    }

But I am getting nullPointer Exception in my Activity. If I remove Thread from this method then it works correctly. What should I do?

Thanks

Because your thread finishes its work later than expected. you should synchronize the thread and ui thread.
Have a look at AsyncTask of Android.

The method will always return null , because newsList gets initialized after you return it. So mNewsList will be null and will not be updated by the thread (which will update newsList but not mNewsList ).

For testing/demonstration: add a Thread.sleep(500) right before your return statement - then it works as expected.


Here's a quick solution to your problem:

public ArrayList<NewsPojo> getNewsList() {
    Log.v("TAG", ""+newsList);
    if(newsList == null)
    {
        newsList = new ArrayList<NewsPojo>(); // <-- new statement!
        Thread t = new Thread(){
           // same lines of code EXCEPT "newsList = new ArrayList<NewsPojo>();" !!
        };
        t.start();
    }
    return newsList;
}

But keep in mind - the newList will be created in time but populated later, in parallel to the main thread. When you look at mNewsList , then it may show an empty or partially filled list. That's the usual behaviour if you do things asynchronously. If you don't want that: don't use a thread to create/populate the list.

Additionally to my comment to your question.

First, try to avoid using Threads in such a way. Use AsyncTask instead. On it's preExecute show some dialog to the user, that you are loading a list, on it's doInBackground put your logic that will return new list, and in postExecute just dismiss the dialog and proceed.

You get NullPointerException, because you initialise newsList in different thread:

newsList = new ArrayList<NewsPojo>();

But this code is executed probably AFTER you return newsList, that equals null

    if(newsList == null)
    {
        Thread t = new Thread(){
                ....
        };// end of thread
        t.start(); // << this only starts thread and continues executing
    }//end of if

    return newsList; // this is executed before newsList is initialized in t.run()

If you have to kill the Activity before the AsyncTask finish the job, you can recover the it in another Activity using:

  1. class code: private class DownloadImageTask extends AsyncTask {.... }

  2. instance of the class:

     dtdodo = new DownloadImageTask( this, p, codacaovalue); dtdodo.execute("wwwkjhdijdh");
  3. Kill the Activity (event like rotate the screen).

  4. recovering the AsyncTask:


   onCreate(){
        Object retained = getLastNonConfigurationInstance();
        if ( retained instanceof DownloadImageTask ) {
                dtdodo = (DownloadImageTask) retained;
                dtdodo.setActivity(this);
        } else {
                dtdodo = new DownloadImageTask(this , 1 , codacaovalue);
                dtdodo.execute();
        }
}

I found this in a blog of a anonymous guy, I am just sharing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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