【问题标题】:How to force main Acivity to wait for subactivity in Android?如何强制主 Activity 等待 Android 中的子 Activity?
【发布时间】:2010-05-21 06:13:07
【问题描述】:

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

     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() 方法(程序抛出错误)。

【问题讨论】:

    标签: android android-activity blocking wait subactivity


    【解决方案1】:

    可能是我遗漏了一些东西,但为什么不直接使用startActivityForResultonActivityResult 机制呢?您可以从您的子活动中获得结果,从它产生的意图中获得结果。
    编辑:顺便说一句,据我了解,如果您将从Activity 代码运行Object.wait(),如果将保持UI 胎面,则可能导致Application not responding 错误。

    【讨论】:

      【解决方案2】:

      我同意 Nikolay 的观点,这绝对是 android 的做法。

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

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

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

      尝试习惯 android activity lifecycle 的工作方式。使用这种方法将减少使用的内存并获得更好的用户体验。

      【讨论】:

        【解决方案3】:

        查看Notepad example,它正好涵盖了这种情况。正如其他人所说,Android 的方式是让你的第一个活动启动你的第二个活动(不是子活动!)并异步监听响应(不是暂停或等待,不需要加入等)。

        【讨论】:

          【解决方案4】:

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

          有一个单例类,我们称之为 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();
                     }
                 }
          }
          

          【讨论】:

          • 此代码编译但不触发子活动。如果 ChildActivity 正在运行,我在 OnCreate 中有消息要记录,但日志中没有这样的条目。我不知道出了什么问题;>
          • 尝试推杆....................... ..................... 单例 si = Singleton.getInstance();同步(si){ si.wait(); } 在 postDelayed(...);
          • 我不熟悉 postDelay(r,t);但我读过它并尝试但不成功,“应用程序没有响应,强制关闭”我认为等待和通知在 android 中无法正常工作
          • 我需要这样的东西!
          【解决方案5】:

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

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

          我在我的应用程序中做了类似的事情,恕我直言,这样做有充分的理由(不要在应用程序启动或恢复时用登录屏幕打扰用户,应用程序会尝试重复使用存储在安全位置且仅在万一它失败了,它会显示这个登录屏幕.所以是的,基本上我的应用程序中的任何活动都可以“暂停”并等待用户在登录活动中提供正确的凭据,然后登录屏幕完成并且应用程序准确地继续它得到的位置暂停(在父活动中)。

          在代码中应该是这样的:

          父活动:

             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;
                  }
              }
          }
          

          儿童活动:

          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);
              }
          
          }
          

          【讨论】:

            猜你喜欢
            • 2011-03-31
            • 2017-07-09
            • 1970-01-01
            • 2015-03-24
            • 1970-01-01
            • 2013-05-23
            • 1970-01-01
            • 2014-03-08
            • 2012-04-09
            相关资源
            最近更新 更多