等到用户实际看到屏幕上的内容

时间:2013-11-21 21:50:10

标签: android android-fragments android-asynctask

我有一个主要的Activity,我的片段的额外类,在这个片段里面是一个AsyncTask,它收集来自各种android库(Wifi SSID,BSSID等)的数据。当我启动我的应用程序时,该应用程序显示一个空白屏幕,没有任何UI。然后在大约2秒后,显示整个数据。我实际上想在背景中将我的TextView显示为“未连接到wifi网络”,同时显示ProgressDialog直到显示数据。我在MainActivity中有ProgressDialog,并在我的AsyncTask onProgressUpdate中调用它

MainActivity.progressDialog = ProgressDialog.show(MainActivity.c,
                                              "ProgressDialog Title",
                                              "ProgressDialog Body");

我在doInBackground方法中更新我的TextViews(通过片段外的另一个方法)

((Activity) getActivity()).runOnUiThread(new Runnable() {

Blank Activity

3 个答案:

答案 0 :(得分:2)

评论太大了所以我会把它放在这里。

听起来你正在以不正确的方式使用片段和AsyncTask。你永远不应该在doInBackground中做任何与UI相关的事情。

以下是您可以做的一个示例。

我假设以下情况:

  • 您有一项主要活动
  • 您有一个包含TextViews的片段
  • 您希望在使用带有progressDialog的AsyncTask加载某些数据后填充TextViews

方法是:

  1. 在活动的onCreate中添加片段(如果片段未在布局中定义,则会自动添加)。
  2. 在您的片段中创建AsyncTask,如下所示:

    private class LoadData extends AsyncTask<Void, Void, List<String>> {
    ProgressDialog progressDialog;
    //declare other objects as per your need
    @Override
    protected void onPreExecute()
    {
        // getActivity() is available in fragments and returns the activity to which it is attached
        progressDialog= new ProgressDialog(getActivity());
    
        progressDialog.setTitle("ProgressDialog Title");
        progressDialog.setMessage("ProgressDialog Body");
        progressDialog.setIndeterminate(true)
        progressDialog.setCancelable(false)
        progressDialog.show();
    
        //do initialization of required objects objects here                
    };      
    
    @Override
    protected Void doInBackground(Void... params)
    {   
        List<String> results = new ArrayList<String>();
        //do loading operation here  
        //add each of the texts you want to show in results
        return results;
    }       
    
    // onPostExecute runs on UI thread
    @Override
    protected void onPostExecute(List<String> results )
    {
        progressDialog.dismiss();
        // iterate results and add the text to your TextViews
        super.onPostExecute(result);
    };
    }
    
  3. 在片段的onCreate中启动AsyncTask:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        new LoadData().execute();
        super.onCreate(savedInstanceState);
    }
    
  4. 这样你就可以避免直接回调你的活动,这在你的场景中真的不需要(除非我误解了)。

    否则请发布所有相关代码和布局。

答案 1 :(得分:1)

这一行:

  

我正在更新doInBackground方法中的TextViews

指出你的问题。您需要使用AsyncTask方法onProgressUpdate()发布到UI线程。您不能直接致电onProgressUpdate(),而是致电publishProgress()

有趣的是,我昨天在这里回答了类似的问题:android AsyncTask in foreach

它包含一个例子。

答案 2 :(得分:1)

这是你需要做的。

(1)从运行收集数据的代码的位置开始,首先应显示进度对话框。像这样:

busy = new ProgressDialog (this);
busy.setMessage (getString (R.string.busy));
busy.setIndeterminate (true);
busy.setCancelable (false);
busy.show();

(2)然后开始收集数据。这必须在一个单独的线程(或Runnable)中完成。做这样的事情:

Thread thread = new Thread ()
{
  @Override
  public void run()
  {
    try
    {
      ... gather data ...

      Message msg = handler.obtainMessage();
      msg.what = LOADING_COMPLETE;
      msg.obj = null;
      handler.sendMessage (msg);
    }
    catch (Exception e)
    {
      Message msg = handler.obtainMessage();
      msg.what = LOADING_FAILED;
      msg.obj = e.getMessage(); // maybe pass this along to show to the user
      handler.sendMessage (msg);
    }

    // get rid of the progress dialog
    busy.dismiss();
    busy = null;
  }
}

(3)向活动添加处理程序,以便在数据收集完成时接收通知:

Handler handler = new Handler()
{
  @Override
  public void handleMessage (Message msg)
  {
    if (msg.what == LOADING_COMPLETE)
      loadingComplete ();
    else if (msg.what == LOADING_FAILED)
      loadingFailed ((String)msg.obj); 
  }
};

(4)实现处理程序:

private void loadingComplete ()
{
  ...
}

private void loadingFailed (String errorMessage)
{
  ...
}

这是必需品。