Android中Thread.sleep方法的替代方法

4

我有一个按钮,点击后可以将文本字段中输入的详细信息保存到Google App Engine。在onClick事件处理完毕之后,我会启动一个新活动的intent,显示我刚刚输入的详细信息。 以下是此操作的代码:

submitButton.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            if(v.getId() == R.id.userDetailsCaptureButton) {
                new EndpointsTask().execute(getApplicationContext());
            }

            startActivity(userProfileDisplayIntent);
        }
    });

现在我希望在调用new EnpointsTask().execute(getApplicationContext)后等待几秒钟再调用startActivity。我了解到使用Thread.sleep会导致UI冻结,因此不太适合这种情况。还有哪些其他选项可供选择?


1
为什么在开始活动之前需要等待几秒钟? - Luiggi Mendoza
为了使我正在尝试检索的数据能够持久化。 - Ojonugwa Jude Ochalifu
也许你应该使用一个CountDownTimer? - A.S.
我不明白你的意思。如果您检索的数据和要启动的活动在同一个线程中,则它将按预期工作。最好发布您当前(期望的)设计并询问相关问题。 - Luiggi Mendoza
3
如果需要持续数据,应该等待持久化完成,而不是人为地延迟执行。 - Darkhogg
你是绝对正确的。 - Ojonugwa Jude Ochalifu
3个回答

6
解决方法是使用一个带有可运行的处理程序,并使用'postDelayed'方法。例如:
new Handler().postDelayed(new Runnable() {
    public void run () {
        // Do delayed stuff!
    }
}, 5000L); //5 seconds delay 

根据你的示例,我做了以下操作:`submitButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub if(v.getId() == R.id.userDetailsCaptureButton) { new EndpointsTask().execute(getApplicationContext());new Handler().postDelayed(new Runnable() { public void run () { // 执行延迟的任务! startActivity(userProfileDisplayIntent); } }, 5000L); } }});`它可以工作。但正如Darkhogg上面提到的,最好等待持久性完成。 - Ojonugwa Jude Ochalifu
如果你想在任务完成后执行某些操作,我建议你考虑使用AsyncTask。通过它的'onPreExecute'和'onPostExecute'回调函数,你可以在线程工作完成前后做一些事情。而'doInBackground'方法则是你可以完成工作的地方,它运行在不同的线程上。这里有一个使用AsyncTask的例子:https://dev59.com/0Gkw5IYBdhLWcg3wwNN5#9671602 - PieterAelse

2

启动活动

onPostExecute()

of

EndpointsTask

您的EndPoints任务应该像这样:
public final class EndpointsTask extends AsyncTask {

    private final Intent mUserProfileDisplayIntent;
    private final WeakReference<Activity> mActivityReference;

    EndpointsTask(final Activity activity, final Intent userProfileDisplayIntent) {
        mActivityReference = new WeakReference<Activity>(activity);
        mUserProfileDisplayIntent = userProfileDisplayIntent;
    }

    @Override
    protected void onPostExecute(Void result) {
        final Activity activity = mActivityReference.get();
        if (activity != null) {
            startActivity(mUserProfileDisplayIntent);
        }
    }
}

然后

    @Override
    public void onClick(View v) {
        if(v.getId() == R.id.userDetailsCaptureButton) {
            // make sure only one task can be launched
            if (endPointsTask == null || endPointsTask.getStatus() != AsyncTask.Status.RUNNING) {
                 endPointsTask = new EndpointsTask(YourActivity.this);
                 endPointsTask.execute();
            }
        }
        startActivity(userProfileDisplayIntent);
    }

// always cancel AsyncTasks in onStop(). You don't want it to launch anything when minimized, do you?

@Override
protected void onStop() {
    super.onStop();
    if (endPointsTask != null && endPointsTask.getStatus() == AsyncTask.Status.RUNNING) {
        endPointsTask.cancel();
    }
}

不要将Context作为参数传递给任何线程,因为这可能会导致内存泄漏。这也意味着内部类应该是静态的。 将Context存储为WeakReference(在当前示例中使用mActivityReference作为Context)。


@OjonugwaOchalifu 你说你不能?其实你可以生成任何你想要的东西。我相信一定有办法的。 - Yaroslav Mytkalyk
我的意思是修改它意味着我必须去改变很多其他的东西。 - Ojonugwa Jude Ochalifu
@OjonugwaOchalifu AsyncTask 应该执行排序操作并传递结果。如果难以修改,可能是设计不良。如果您不需要启动任何内容或启动不同的内容,请考虑将其抽象化,并创建实现抽象启动方法或适合您需求的其他任务。 - Yaroslav Mytkalyk
我并不是说修改是不可能的,只是因为我对此很陌生,如果现在改动代码,那么我将很难跟上自己所做的工作。 - Ojonugwa Jude Ochalifu

1

尝试使用Handler和postDelayed方法在onClick内部执行


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接