【问题标题】:How can I run an AsyncTask with a dialog after finishing activity?完成活动后,如何使用对话框运行 AsyncTask?
【发布时间】:2013-03-21 12:04:42
【问题描述】:

我有两个活动,一个用于显示条目,另一个用于创建它们。这是一个标准用例:

  • 用户打开应用程序并显示条目。
  • 用户单击按钮创建新条目并打开新活动。
  • 用户完成创建条目并点击“完成”。
  • 活动以 setResult() 和 finish() 结束。

我要添加的是在查看活动完全加载后运行的 AsyncTask。 此 AsyncTask 在运行时显示一个对话框。问题是,当我像这样将这段代码放入 onActivityResult() 时:

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) {     
    super.onActivityResult(requestCode, resultCode, data); 
        switch(resultCode) { 
        case (Activity.RESULT_OK): {
            mEntryListFragment.updateContent();
            runAsyncTaskHere();
        }
    }
}

它在返回主活动之前运行 AsyncTask,并且不显示任何对话框。有什么想法我能做什么?

编辑:这里是 AsyncTask。

public static class LogInTask extends AsyncTask<String, Void, Integer> {
    protected String username = "";
    protected String password = "";
    protected ProgressDialog dialog;
    protected boolean showDialogs;

    public LogInTask(boolean sd) {
        this.showDialogs = sd;
    }

    @Override
    protected void onPreExecute() {
        if (this.showDialogs) dialog = ProgressDialog.show(MainActivity.getContext(), null, "Logging in...");
    }

    @Override
    protected Integer doInBackground(String... login) {
        if (Config.DEBUG) Log.d(Config.APP_NAME, "in doInBackground() of LogInTask");
        HttpResponse response = null;
        String username = login[0];
        String password = login[1];
        try {
            HttpPost httpPost = new HttpPost(URL_BASE + URL_LOGIN);

            // main (JSON) login method
            JSONObject json = new JSONObject().put("user", 
                    new JSONObject()
                        .put("email", username)
                        .put("password", password)
                        .put("remember_me", Config.REMEMBER_LOGIN)
                    );
            this.username = username;
            this.password = password;
            StringEntity se = new StringEntity(json.toString());
            httpPost.setHeader("Accept", "application/json");
            httpPost.setHeader("Content-type", "application/json");
            httpPost.setEntity(se);

            response = httpclient.execute(httpPost);
            String responseEntity = EntityUtils.toString(response.getEntity());
            JSONObject result = new JSONObject(responseEntity);
            return result.getBoolean("success") ? 1 : KEY_ERROR; // Return 1 if successful and -1 if not
        } catch (UnknownHostException e) {
            e.printStackTrace();
            KEY_ERROR;
        } catch (Exception e) {
            e.printStackTrace();
            return KEY_ERROR;
        }
    }

    @Override
    protected void onPostExecute(Integer result) {
        if (this.showDialogs) {
            dialog.dismiss();
            String text = result == 1 ? "Login was successful." : "Login failed!";
            makeToast(text);
        }
    }
}

编辑 2:我试过这个:

boolean needToUpdate = false;
@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) {     
    super.onActivityResult(requestCode, resultCode, data); 
    switch(resultCode) { 
        case (Activity.RESULT_OK): {
            mEntryListFragment.updateContent();
            needToUpdate = true;
        }
    }
}

@Override
public void onResume() {
    super.onResume();
    if (needToUpdate) {
        runAsyncTaskHere();
        mEntryListFragment.updateContent();
    }
    needToUpdate = false;
}

它做了同样的事情。

编辑 3:这里是 AndroidManifest 的相关部分:

 <activity 
        android:name=".MainActivity" 
        android:label="@string/app_name"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".AddEntryActivity"
        android:label="@string/app_name"
        android:screenOrientation="portrait"
        android:configChanges="orientation" />

【问题讨论】:

    标签: android


    【解决方案1】:

    AsyncTask 是一个用于后台处理的类,请不要尝试使用它来对您的 UI 或活动进行某些操作,它总是会导致不良且不可预测的行为。

    也许我应该详细说明一下。活动来来去去,被杀死和恢复,被摧毁和重建,这是他们通常的生活方式。这很正常。

    您的AsyncTask 可能很容易比您的Activity 寿命更长,因此当您尝试访问 UI 时,它已经消失了。再次销毁并重新创建,你所拥有的只是一个死指针,它给你一个例外。将您的文件加载到AsyncTask,进行联网,访问数据库。只是不要尝试访问 UI/Activity,否则您的应用程序最终会崩溃和烧毁。

    【讨论】:

    • 如果是这样,我应该在哪里做网络?这就是我一直认为我应该做网络任务的地方。
    • AsyncTask 中建立网络,但不要在那里做 UI 工作。
    • 我就是这么想的。正如我的代码所示,我正在做的唯一 UI 是 ProgressDialog。我真的只需要弄清楚为什么它在第二个活动完成之前运行并被第一个取代。
    • 您需要一个进度对话框的上下文,当您的数据加载完成时,您的用户可能已经按下“主页”按钮或旋转设备,以及您的Activity(及其Context)离开了。猜猜,当你尝试用死的上下文做任何事情时会发生什么......
    • 这个应用程序被锁定为纵向 - 但我知道你来自哪里。那么,我应该把我的 ProgressDialog 放在哪里?
    【解决方案2】:
    1. 当您单击按钮创建新条目时,启动新活动。但保持活动与条目。意图后不要调用finish()。
    2. 创建后,点击完成,关闭当前活动。(调用完成())
    3. mEntryListFragment.updateContent 将此方法写在显示条目的activity的onStart()中。

    【讨论】:

    • 我试过这个,它没有改变任何东西;我不知道这是怎么回事!
    • 您必须再次获取条目并设置列表的适配器以反映 mEntryListFragment.updateContent() 方法中的更改(添加新条目)
    • 我假设您正在使用异步任务获取条目(可能从数据库中获取)。或者你用来为列表适配器创建条目的任何东西都应该放在 updateContent() 中,并且 listview.setAdapter(your adapter) 必须在最后调用。我希望你和我在同一条轨道上,我已经正确理解了你的问题。
    • 主要是 - 我从 SQLite 数据库中获取条目,并且 AsyncTask 正在将它们上传到服务器。问题是 AsyncTask 正在冻结 UI 线程,而没有像预期的那样显示 ProgressDialog。
    • 您的 SQLite DB 是否与服务器同步。?我的意思是当您使用异步任务向服务器添加条目时,您的 SQLite 数据库是否也会更新。如果是这样,使用具有 listview.setAdapter() 的 updateContent() 方法将内容加载到 listview 必须根据需要显示更改。
    【解决方案3】:

    使用ProgressDialog 来实现这一点。启动对话框 onPreExecute() 并完成它 onPostExecute() 方法。您必须在异步任务中覆盖这些方法。

    【讨论】:

    • 这正是我现在的做法。等一下,我也会发布我的 asynctask 代码。
    • 然后在 onResume 中调用你的方法。如果通过 onActivityResult() 方法可以使用 flag。
    • 顺便说一句,您的活动的任务是什么?如果您使用单个任务,您就不能拥有 onActivityResult()。另外,您真的想在 MainActivty 中拥有静态上下文吗?
    • 我确信 showDialogs 是真的,是的。我的活动的任务是什么意思?我使用startActivityForResult(intent, 0); 启动了我的第二个活动,并且我确定 onActivityResult 正在运行。
    • 你能在 AndroidManifest 中发布 Activity 的声明吗?
    【解决方案4】:

    我认为,你必须使用回调的概念,

    像以往一样,加载完成,实现你的callback,你可以在其中处理AsyncTask,在doInBackGround()中执行你的任务后,你可以使用onPostExecute()

    试试这样的,

    Callback_interface
    {
        void async_run_after_some_time() ;
    }
    
    main_activity_class extends Activity Implements Callback_interface
    {
        void async_run_after_some_time()
        {
            // implement your toast here 
        }
    }
    
    onPostExecute()
    {
        main_activity_class ob = new main_activity_class ();
        ob.async_run_after_some_time();
    }
    

    【讨论】:

      【解决方案5】:

      只是一个想法。

      1. 您确定要检索正确的上下文吗?
      2. 布尔值设置是否正确?

      另外,我相信您正在使用 HttpCore。据我所知,由于它的粒度(与默认情况下可用的 HttpConnection 类相比),它需要更多注意网络和断开/连接。因此,我不认为将它与 AsyncTask 类一起使用是最好的,因为它们与 UI 线程几乎没有联系。因此,不要给用户太多控制权,并且可能会超出应用程序的生命周期。

      【讨论】:

      • 我认为它一定是上下文,但我不确定,是的,布尔值是正确的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-01
      • 1970-01-01
      • 2014-04-24
      • 1970-01-01
      • 2013-01-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多