简体   繁体   中英

How to overcome “Can't create handler inside thread that has not called Looper.prepare()” issue?

I am trying to create fragments inside viewpager. In the adapter I am using threads to create fragments. Inside thread I am executing AsyncTask which further fetches the fragments. Inside each fragment class(OneFragment, TwoFragment), I have AsyncTask which access some API from web. The appliction works fine if I am not using thread and AsyncTask at all. I am using this for smoother UI performance. But it is fetching error. I have gone through some already existing topics on the same issue. But I could not figure out the reason for this. Can anyone point out what am I doing wrong here?

Here is my adapter class and AsyncTask class:

class SectionsPagerAdapter extends FragmentStatePagerAdapter {
     Activity activity;
     Fragment f = null;
public SectionsPagerAdapter(FragmentManager fm, Activity activity) {
    super(fm);
    this.activity = activity;
}

@Override
public Fragment getItem(int i) {        
    switch (i) {
    case 0: {           
        activity.runOnUiThread(new Runnable() {
            public void run() {
        try {
             f =  new FetchFragment().execute("one").get();             
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
            }
        });             
        return f;
    }
    case 1: {
        activity.runOnUiThread(new Runnable() {
            public void run() {
        try {
             f =  new FetchFragment().execute("two").get();             
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
            }
        });             
        return f;
    }
    }
    return null;
}

@Override
public int getCount() {
    return 2;
}

@Override
public CharSequence getPageTitle(int position) {
    switch (position) {
    case 0:
        return "one";
    case 1:
        return "two";
    }
    return null;
}


class FetchFragment extends AsyncTask<String, Void, Fragment>
{   
@Override
protected Fragment doInBackground(String... arg0) {     
    if(arg0[0].equalsIgnoreCase("one"))
    {
        Fragment fragment = new OneFragment();
        Bundle args = new Bundle();
        args.putInt(CategoriesFragment.ARG_SECTION_NUMBER, 1);
        fragment.setArguments(args);
        return fragment;
    }
    if(arg0[0].equalsIgnoreCase("two"))
    {
        Fragment fragment = new TwoFragment();
        Bundle args = new Bundle();
        args.putInt(FeaturedFragment.ARG_SECTION_NUMBER, 2);
        fragment.setArguments(args);
        return fragment;
    }       
    return null;
}

@Override
 protected void onPostExecute(Fragment fragment){}
}
}

Here is my error log.

10-23 12:52:28.835: E/AndroidRuntime(17485): FATAL EXCEPTION: AsyncTask #3
10-23 12:52:28.835: E/AndroidRuntime(17485): java.lang.RuntimeException: An error occured while executing doInBackground()
10-23 12:52:28.835: E/AndroidRuntime(17485):    at android.os.AsyncTask$3.done(AsyncTask.java:299)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at java.lang.Thread.run(Thread.java:856)
10-23 12:52:28.835: E/AndroidRuntime(17485): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
10-23 12:52:28.835: E/AndroidRuntime(17485):    at android.os.Handler.<init>(Handler.java:121)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at android.support.v4.app.ListFragment.<init>(ListFragment.java:47)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at com.store.fragments.OneFragment.<init>(OneFragment.java:68)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at com.store.adapter.SectionsPagerAdapter$FetchFragment.doInBackground(SectionsPagerAdapter.java:173)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at com.store.adapter.SectionsPagerAdapter$FetchFragment.doInBackground(SectionsPagerAdapter.java:1)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at android.os.AsyncTask$2.call(AsyncTask.java:287)
10-23 12:52:28.835: E/AndroidRuntime(17485):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)

Ok, you're doing it wrong with asynctasks. Usually asynctasks are used for some time-consuming operations that should be processed in background, but you're trying to run it onUiThread. And in asynctask you're trying to modify UI in doInBackground(), while it's strongly recommend to do it in onPostExecute()

You should not do any UI updations in AsyncTask's doInBackground() .ALl the UI operations must be in onPostExecute() . To know more Study here

See my previous Post too

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