Android 中如何强制主 Activity 等待子 Activity?

发布于 2024-09-02 18:15:22 字数 667 浏览 1 评论 0原文

我正在从主活动中调用子活动。此子活动应该从用户那里获取一些数字(我正在使用编辑文本控件来实现此目的),将它们保存到另一个类中的静态变量并终止。我希望主活动等待子活动,但两者只是同时运行。即使这样做也无济于事:

     Thread t = new Thread(new Runnable(){
     public void run(){
     Log.v("==================", "run "+new Date());
     startActivityForResult(new Intent(ctx,myCustomSubactivity.class),1);  
     } });
     Log.v("==================", "calling run "+new Date());
     t.start();      
     try {
        t.join();
    } catch (InterruptedException e) {Log.v("==================", "can't join");}
    Log.v("==================", "back from activity "+new Date());

您知道如何强制主要活动等待吗? Android 不支持 Thread.wait() 方法(程序抛出错误)。

I am calling a subactivity from main activity. This subactivity should take few numbers from user (i'm using Edit text control to achieve this), save them to static variable in another class and terminate. I want main activity to wait for subactivity but both are just running simultaneously. Even doing sth like that doesn't help:

     Thread t = new Thread(new Runnable(){
     public void run(){
     Log.v("==================", "run "+new Date());
     startActivityForResult(new Intent(ctx,myCustomSubactivity.class),1);  
     } });
     Log.v("==================", "calling run "+new Date());
     t.start();      
     try {
        t.join();
    } catch (InterruptedException e) {Log.v("==================", "can't join");}
    Log.v("==================", "back from activity "+new Date());

do you know how to force main activity to wait? Thread.wait() method is not supported in Android(program throws error).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

悸初 2024-09-09 18:15:22

可能我错过了一些东西,但为什么不只使用 startActivityForResultonActivityResult 机制呢?您可以根据子活动产生的意图获得结果。
编辑:顺便说一句,据我所知,如果您从 Activity 代码中运行 Object.wait() ,如果将保持 UI 线程,可能会导致 应用程序不响应错误。

May be I'm missing something but why don't just use startActivityForResult and onActivityResult mechanism? You could get result from you subactivity from intent it was resulted with.
Edit: BTW as far as I understand, if you will run Object.wait() from Activity code if will hold UI tread whitch can result in Application not responding error.

中性美 2024-09-09 18:15:22

我同意 Nikolay 的观点,这绝对是 Android 的方式。

使用 startActivityForResult 启动子活动 在子活动中使用 setResult 添加结果代码和意图,其中包含数据包中所需的所有数字。

在您的第一个活动中覆盖 onActivityResult 并从 Intent 中检索数字。

如果您使用静态变量,这在一开始似乎更容易,但它非常不安全,并且在某些情况下这可能不起作用。如果您的程序发送到后台,您的活动将被保存,但如果手机内存不足,系统将关闭您的程序,在用户恢复它后,一切看起来就像用户离开它的那一刻,但静态变量将被重新创建它们的初始化值。

尝试习惯 android Activity 生命周期 的工作方式。使用这种方法将减少使用的内存并提供更好的用户体验。

I agree with Nikolay this is definitely the android way to do this.

Start the subactivity with startActivityForResult in the sub activity use setResult to add an result code and an intent with all the numbers you need in the data bundle.

In your first activity overwrite onActivityResult and retrieve the numbers from the Intent.

If you use the static variable this seems easier in the first moment but it is very insecure and there are some cases this may not work. If your program is send to the background your activities will be saved but if the phone runs low on memory the system will close your program and after the user resumes it everything looks like the moment the user left it but the static variables will be recreated to their initialization value.

Try to get used to the way the android activity lifecycle works. Using this approach will result in fewer used memory and a much better user experience.

夏花。依旧 2024-09-09 18:15:22

查看记事本示例,它恰好涵盖了这种情况。正如其他人所说,Android 方式是让您的第一个 Activity 启动您的第二个 Activity(而不是子 Activity!)并异步侦听响应(而不是暂停或等待,无需加入等)。

Check out the Notepad example, it covers exactly this situation. And as others have said, the Android way is to have your first activity start up your second activity (not sub-activity!) and asynchronously listen for a response (not pause or wait, no need for joining, etc.).

栀梦 2024-09-09 18:15:22

嗯...你可以这样做(顺便说一句,没有直接的方法):

有一个单例类,我们称之为 Monitor:

public class Singleton
{
   private Singleton() { }
   private static Singleton instance = new Singleton();

   public static Singleton getInstance() {
      return instance;
   }
}

public class ParentActivity extends Activity
{
    private void startAndWait()
    {
        Intent i = new Intent();
        // initialize i
        startActivityForResult(i);
        Singleton si = Singleton.getInstance();
        synchronized(si)
        {
             si.wait();
        }
        //do remaining work
    }
}

public class ChildActivity extends Activity
{
       protected void onCreate(Bundle savedInstance)
       {
           //do all the work
           Singleton si = Singleton.getInstance();
           synchronized(si)
           {
             si.notify();
           }
       }
}

Well... you can do it like this (btw, there's not straight forward way):

Have a singleton class, let's call it Monitor:

public class Singleton
{
   private Singleton() { }
   private static Singleton instance = new Singleton();

   public static Singleton getInstance() {
      return instance;
   }
}

public class ParentActivity extends Activity
{
    private void startAndWait()
    {
        Intent i = new Intent();
        // initialize i
        startActivityForResult(i);
        Singleton si = Singleton.getInstance();
        synchronized(si)
        {
             si.wait();
        }
        //do remaining work
    }
}

public class ChildActivity extends Activity
{
       protected void onCreate(Bundle savedInstance)
       {
           //do all the work
           Singleton si = Singleton.getInstance();
           synchronized(si)
           {
             si.notify();
           }
       }
}
美人骨 2024-09-09 18:15:22

我不是在这里判断这是否是一个好的模式,但是如果您确实需要一个活动来等待子活动,您可以尝试这种方法:

  • 定义一个对象(锁),两个活动通过该对象进行同步;这也可以(应该)作为在这两个活动之间交换数据的对象,因此应该在父活动中定义为静态
  • ,在异步任务中启动一个异步任务(因为UI主线程不能处于等待状态)
  • ,启动你的子活动
  • 异步任务等待锁,直到它收到通知
  • 子活动执行它需要的任何操作,并在完成时通知等待线程

我在我的应用程序中做了类似的事情,恕我直言,这样做有一个很好的理由(不是为了在应用程序启动或恢复时使用登录屏幕打扰用户,该应用程序会尝试重新使用存储在安全位置的凭据,只有在失败的情况下,它才会显示此登录屏幕,所以是的,基本上我的应用程序中的任何活动都可以获取“暂停”并等待,直到用户在登录活动中提供正确的凭据,登录屏幕完成后,应用程序将在暂停的地方继续运行(在父活动中)。

在代码中,它会是这样的:

ParentActivity:

   public class ParentActivity extends Activity {
    private static final String TAG = ParentActivity.class.getSimpleName();

    public static class Lock {
        private boolean condition;

        public boolean conditionMet() {
            return condition;
        }

        public void setCondition(boolean condition) {
            this.condition = condition;
        }
    }

    public static final Lock LOCK = new Lock();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.parent_layout);

        // do whatever logic you need and anytime you need to stat sub-activity
        new ParentAsyncTask().execute(false);
    }

    private class ParentAsyncTask extends AsyncTask<Boolean, Void, Boolean> {

        @Override
        protected Boolean doInBackground(Boolean... params) {
            // do what you need and if you decide to stop this activity and wait for the sub-activity, do this
            Intent i = new Intent(ParentActivity.this, ChildActivity.class);
            startActivity(i);
            synchronized (LOCK) {
                while (!LOCK.conditionMet()) {
                    try {
                        LOCK.wait();
                    } catch (InterruptedException e) {
                        Log.e(TAG, "Exception when waiting for condition", e);
                        return false;
                    }
                }
            }
            return true;
        }
    }
}

ChildActivity:

public class ChildActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.child_layout);

        // do whatever you need in child activity, but once you want to finish, do this and continue in parent activity
        synchronized (ParentActivity.LOCK) {
            ParentActivity.LOCK.setCondition(true);
            ParentActivity.LOCK.notifyAll();
        }
        finish();

        // if you need the stuff to run in background, use AsyncTask again, just please note that you need to
        // start the async task using executeOnExecutor method as you need more executors (one is already occupied), like this:
        // new ChildAsyncTask().executeOnExecutor(ChildAsyncTask.THREAD_POOL_EXECUTOR, false);
    }

}

I'm not here to judge if it's a good pattern or not but if you really need an activity to wait for a sub-activity, you can try this approach:

  • define an object (lock) over which the two activities get synchronized; this can (should) also work as the object to exchange data between those two activities and thus should be defined as static
  • in parent activity, start an async task (as the UI main thread cannot be in waiting state)
  • in the async task, start your sub-activity
  • the async task waits on the lock till it gets notified
  • the sub-activity does whatever it needs and notifies the waiting thread when it finishes

I did a similar thing in my app and IMHO had a good reason for this (not to bother a user with login screen upon app start or resume, the app tries to re-use credentials stored in a secured place and only in case it fails, it shows this login screen. So yes, basically any activity in my app can get "paused" and waits till the user provides correct credentials in the login activity upon which the login screen finishes and the app continues exactly where it got paused (in the parent activity).

In the code it would be something like this:

ParentActivity:

   public class ParentActivity extends Activity {
    private static final String TAG = ParentActivity.class.getSimpleName();

    public static class Lock {
        private boolean condition;

        public boolean conditionMet() {
            return condition;
        }

        public void setCondition(boolean condition) {
            this.condition = condition;
        }
    }

    public static final Lock LOCK = new Lock();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.parent_layout);

        // do whatever logic you need and anytime you need to stat sub-activity
        new ParentAsyncTask().execute(false);
    }

    private class ParentAsyncTask extends AsyncTask<Boolean, Void, Boolean> {

        @Override
        protected Boolean doInBackground(Boolean... params) {
            // do what you need and if you decide to stop this activity and wait for the sub-activity, do this
            Intent i = new Intent(ParentActivity.this, ChildActivity.class);
            startActivity(i);
            synchronized (LOCK) {
                while (!LOCK.conditionMet()) {
                    try {
                        LOCK.wait();
                    } catch (InterruptedException e) {
                        Log.e(TAG, "Exception when waiting for condition", e);
                        return false;
                    }
                }
            }
            return true;
        }
    }
}

ChildActivity:

public class ChildActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.child_layout);

        // do whatever you need in child activity, but once you want to finish, do this and continue in parent activity
        synchronized (ParentActivity.LOCK) {
            ParentActivity.LOCK.setCondition(true);
            ParentActivity.LOCK.notifyAll();
        }
        finish();

        // if you need the stuff to run in background, use AsyncTask again, just please note that you need to
        // start the async task using executeOnExecutor method as you need more executors (one is already occupied), like this:
        // new ChildAsyncTask().executeOnExecutor(ChildAsyncTask.THREAD_POOL_EXECUTOR, false);
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文