简体   繁体   English

如何强制主要Acivity在Android中等待子活动?

[英]How to force main Acivity to wait for subactivity in Android?

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). Android中不支持Thread.wait()方法(程序抛出错误)。

May be I'm missing something but why don't just use startActivityForResult and onActivityResult mechanism? 可能是我遗漏了一些东西,但为什么不只是使用startActivityForResultonActivityResult机制? 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. 编辑:BTW据我所知,如果你将从Activity代码运行Object.wait()如果将保持UI胎面whitch可能导致Application not responding错误。

I agree with Nikolay this is definitely the android way to do this. 我同意Nikolay这绝对是安卓的方法。

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. 使用setResult在子活动中使用startActivityForResult启动子活动,以使用数据包中所需的所有数字添加结果代码和意图。

In your first activity overwrite onActivityResult and retrieve the numbers from the Intent. 在您的第一个活动中,覆盖onActivityResult并从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. 尝试习惯android 活动生命周期的工作方式。 Using this approach will result in fewer used memory and a much better user experience. 使用此方法将导致更少的已用内存和更好的用户体验。

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.). 正如其他人所说,Android的方式是让你的第一个活动启动你的第二个活动(不是子活动!)并异步监听响应(不是暂停或等待,不需要加入等)。

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) 在父活动中,启动异步任务(因为UI主线程不能处于等待状态)
  • 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: 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: 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);
    }

}

Well... you can do it like this (btw, there's not straight forward way): 嗯......你可以这样做(顺便说一句,这不是直接的方式):

Have a singleton class, let's call it Monitor: 有一个单例类,我们称之为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();
           }
       }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM