Android startactivity 冻结应用

Posted

技术标签:

【中文标题】Android startactivity 冻结应用【英文标题】:Android startactivity freezes the app 【发布时间】:2017-06-17 21:50:45 【问题描述】:

我制作了非常简单的应用程序。基本上,如果按下按钮,我有活动 A 会启动活动 B。这是代码

openMapFAB.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                Intent intent = new Intent(getActivity(), MapActivity.class);
                intent.putExtra("routeId", id);
                startActivity(intent);
            
        );

但这就是问题所在。活动B非常繁重(它基本上是打开地图(mapsforge)并进行其他繁重的计算)。因此,当按下按钮时,我的 UI 冻结了大约 4 秒,然后我打开了活动 B。我想展示一些动画,比如圆形进度条或类似的东西。那么是否可以不在 UI 线程中启动活动?

这是我目前尝试过的

 new Thread(new Runnable() 
                    @Override
                    public void run() 
                        while (progressStatus < 100) 
                            progressStatus += 25;
                            handler.post(new Runnable() 
                                @Override
                                public void run() 
                                    //animation code
                                
                            );

                            try 
                                Thread.sleep(1600);
                                if (progressStatus == 100)
                                    Intent intent = new Intent(getActivity(), MapActivity.class);
                                    intent.putExtra("routeId", id);
                                    startActivity(intent);
                                

                             catch (InterruptedException e) 
                                e.printStackTrace();
                            
                        
                    
                ).start();

但这并不是我所需要的。有什么解决方案或建议吗?

【问题讨论】:

如果繁重的代码在 MapActivity 中,这将不起作用。您应该尝试重构 MapActivity 以将代码移动到例如线程或异步任务。如果您需要帮助,请添加 MapActivity 的代码 【参考方案1】:

1) 那么是否可以不在 UI 线程中启动活动

应仅在主 UI 线程中处理活动。您将无法在其他线程中启动活动。即使在后台线程中处理数据后,也可以使用runOnUiThread 之类的活动方法来调用或推送活动

如果你在主线程中执行长操作,android会抛出ANR

2) 然而,这并不是我所需要的。任何解决方案或 建议?

现在另一种方法是使用AsyncTask 或IntentService 在后台对您的活动进行繁重的操作,并显示进度条,直到这些操作完成。

此操作完成后,将数据发布到您的 MapActivity。

1) Sample Intent Service implementation

2) Sample AsyncTask example

onCreate 上的 AsyncTask 示例如下

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

        new BackAsync().execute("URL");

private String getURLDetailsTitle(String url) 
  //Retrieve data from external URL

//AsyncTask to fetch data from URL called inside onCreate
private class BackAsyncextends AsyncTask<String, String, String> 

    @Override
    protected String doInBackground(String... urls) 
        String str = getURLDetailsTitle(urls[0]);
        while(true) 
           publishProgress(str);

        
        return str;
    

    @Override
    protected void onProgressUpdate(String... progress) 
        //update progress
    

    protected void onPostExecute(Long result) 
         //update UI changes
     

【讨论】:

【参考方案2】:

使用 AsyncTask 并在 doInBackground 方法中启动进度条并在 onPostExecute 方法中关闭它。

【讨论】:

以上是关于Android startactivity 冻结应用的主要内容,如果未能解决你的问题,请参考以下文章

Android - 从 startActivity 获取活动对象

Android startActivities()的使用

应用内部启动startActivity-Android12

应用内部启动startActivity-Android12

Android 系统源码初步阅读之 activity 的 startActivity(intent) 与 非 activity 的 startActivity(...) 的不同

Android 系统源码初步阅读之 activity 的 startActivity(intent) 与 非 activity 的 startActivity(...) 的不同