【问题标题】:multithreading UI : exceptionininitializererror and runtime exception android多线程 UI:exceptionininitializererror 和运行时异常 android
【发布时间】:2013-01-25 17:28:32
【问题描述】:

我正在尝试制作多线程,但我在少数智能手机 (SGS2) 上获得了此堆栈跟踪:

java.lang.ExceptionInInitializerError
at com.android.bordeaux.code.model.AnnouncersContainer.setLoudArrayFromJSON_online(AnnouncersContainer.java:68)
at com.android.bordeaux.code.SplashscreenActivity_Second$1.run(SplashscreenActivity_Second.java:55)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
... 2 more 

这是我的主要活动(启动画面),它在几秒钟内等待我的异步任务完成:

    public class SplashscreenActivity_Second extends Activity 
        {       
            @Override
            public void onCreate(Bundle savedInstanceState) 
            {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.splashscreen_second);

                // thread
                Thread splashThread = new Thread()
                {
                    @Override
                    public void run()
                    {
                        try
                        {
                            int waited = 0;

                            if (isInternetOn())
                            {
// Here I'm making my asynctask !!
AnnouncersContainer.setLoudArrayFromJSON_online(getApplicationContext());
                                while (waited < 5000)
                                {
                                    sleep(50);
                                    waited += 40;
                                }
                            }
                            else
                            {                       
                                AnnouncersContainer.setLoudArrayFromXML_local(getApplicationContext());
                                while(waited < 5000)
                                {
                                    sleep(50);
                                    waited += 60;
                                }
                            }
                        }
                        catch( InterruptedException e )
                        {
                            e.printStackTrace();
                        }
                        finally
                        {
                            Intent intent_to_tabhost = new Intent(SplashscreenActivity_Second.this, MyTabActivity.class);
                            startActivity(intent_to_tabhost);
                            finish();
                        }
                    }
                };
                splashThread.start();
            }
}

这是我的异步任务:

public class DownloadAnnouncers extends AsyncTask<Void, Integer, Boolean>
{
    public static Boolean loadFinished = false;

    //JSON variables..


    private static String url = null;

    Context context;

    public DownloadAnnouncers(Context context) 
    {
        this.context = context;
    }

    @Override
    protected void onPreExecute() 
    {
        super.onPreExecute();
    }

    protected Boolean doInBackground(Void... params) 
    {

    // fine retrieving all my JSON data in a global array..

    }

    @Override
    protected void onPostExecute(Boolean downloadedArray) 
    {
        super.onPostExecute(downloadedArray);
    }
}

我知道问题是我在 UI 中进行多线程处理,但有人可以告诉我如何删除循环线程并将其替换为我的 Asynctask 的 onPostExecute() 方法? (最好等待 asynctask 完成而不是等待..)

或者可以帮助我用多线程纠正这个错误..

编辑:

我的异步任务:

public class DownloadAnnouncers extends AsyncTask<Void, Integer, Boolean>
    {
        public static Boolean loadFinished = false;

        //JSON variables..


        private static String url = null;

        Context context;

        public DownloadAnnouncers(Context context) 
        {
            this.context = context;
        }

        @Override
        protected void onPreExecute() 
        {
            super.onPreExecute();
        }

        protected Boolean doInBackground(Void... params) 
        {

        // fine retrieving all my JSON data in a global array..

        }

        @Override
        protected void onPostExecute(Boolean downloadedArray) 
        {
            super.onPostExecute(downloadedArray);
        Intent intent_to_tabhost = new Intent(context, MyTabActivity.class);
        intent_to_tabhost.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent_to_tabhost);
        }
    }

但是现在如果我按下取消按钮,我将返回到我的启动画面活动.. 我不能在 onPostExecute 方法中执行 ctx.finish()..

【问题讨论】:

    标签: android multithreading android-asynctask runtimeexception


    【解决方案1】:

    您不能在尚未调用Looper.prepare() 的线程内创建Handler,正如您的错误消息所述:

    无法在未调用 Looper.prepare() 的线程内创建处理程序

    处理程序是在AsyncTask 中创建的,所以你一开始看不到它。

    如果您想保持代码原样,您可以通过将 AsyncTask 的创建移到自定义线程之外来修复它。

    但是,您无需创建线程,您只需在 ui 线程中创建 AsyncTask(它将在自己的线程上运行,因此在工作时不会锁定您的手机),然后执行任何操作任务完成后你想要的onPostExecute-方法。

    class ExampleAsync extends AsyncTask<Void, Integer, Boolean>
    {
        public static Boolean loadFinished = false;
        //JSON variables..
        private static String url = null;
        Context context;
    
        public DownloadAnnouncers(Context context){
            this.context = context;
        }
    
        protected Boolean doInBackground(Void... params){
            // fine retrieving all my JSON data in a global array..
        }
    
        @Override
        protected void onPostExecute(Boolean downloadedArray){
            Intent intent_to_tabhost = new Intent(context, MyTabActivity.class);
            startActivity(intent_to_tabhost);
        }
    }
    

    在你的活动中:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splashscreen_second);
        AsyncTask myTask = new ExampleAsync(this);
        myTask.execute();
    }
    

    【讨论】:

      【解决方案2】:

      不要等待 asyncTask ,而是使用 onPostExecute ,它仅在任务完成后在 UI 线程上调用。

      如果活动被破坏(例如,如果用户在显示初始屏幕时按下了后退按钮),您还应该取消任务。

      【讨论】:

      • 终于成功了,我必须将 asynctask 添加到我的启动画面活动中(asynctask 之前不是内部的),所以我可以调用 finish()
      猜你喜欢
      • 2014-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-30
      • 1970-01-01
      • 1970-01-01
      • 2011-12-16
      • 1970-01-01
      相关资源
      最近更新 更多