以编程方式重新启动/重新创build一个活动?

在我的数据库做了一些改动之后,我的观点发生了重大的变化,我想重画,重新执行onCreate。

这怎么可能?

更新:Android SDK 11为活动添加了一个recreate()方法。

我已经通过简单地重复使用开始活动的意图来做到这一点。 在你的类中定义一个intent starterIntent ,并使用starterIntent = getIntent();onCreate()starterIntent = getIntent(); 。 然后当你想重新开始活动时,调用finish(); startActivity(starterIntent); finish(); startActivity(starterIntent);

这不是一个非常优雅的解决scheme,但它是一个简单的方法来重新启动您的活动,并强制它重新加载一切。

调用活动的重新创build方法。

在这里结合一些答案,你可以使用下面的东西。

 class BaseActivity extends SherlockFragmentActivity { // Backwards compatible recreate(). @Override public void recreate() { if (android.os.Build.VERSION.SDK_INT >= 11) { super.recreate(); } else { startActivity(getIntent()); finish(); } } } 

testing

我testing了一下,有一些问题:

  1. 如果活动是堆栈中最低的活动,则调用startActivity(...); finish(); startActivity(...); finish(); 只是存在的应用程序, 并没有重新开始活动。
  2. super.recreate()实际上并不像完全重新创build活动一样。 这相当于旋转设备,所以如果你有任何FragmentsetRetainInstance(true)他们将不会被重新创build; 只是暂停和恢复。

所以目前我不相信有一个可以接受的解决scheme。

当我需要重新启动一个活动时,我使用下面的代码。 虽然不推荐。

 Intent intent = getIntent(); finish(); startActivity(intent); 

对于11之前的API,您不能使用recreate()。 我用这种方式解决了:

 Bundle temp_bundle = new Bundle(); onSaveInstanceState(temp_bundle); Intent intent = new Intent(this, MainActivity.class); intent.putExtra("bundle", temp_bundle); startActivity(intent); finish(); 

并在onCreate ..

 @Override public void onCreate(Bundle savedInstanceState) { if (getIntent().hasExtra("bundle") && savedInstanceState==null){ savedInstanceState = getIntent().getExtras().getBundle("bundle"); } super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //code } 

find姜饼工具recreate ,我想使用下面的代码(姜饼):

 activity.mMainThread.mAppThread.scheduleRelaunchActivity(activity.mToken, null, null, 0, false, null); 

对于这些代码,这是从更高的API执行。

 public void recreate() { if (mParent != null) { throw new IllegalStateException("Can only be called on top-level activity"); } if (Looper.myLooper() != mMainThread.getLooper()) { throw new IllegalStateException("Must be called from main thread"); } mMainThread.requestRelaunchActivity(mToken, null, null, 0, false, null, false); } 

Api-10没有requestRelaunchActivity,但是,从差异,我发现这个:

  public final void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, int configChanges, boolean notResumed, Configuration config) { - ActivityClientRecord r = new ActivityClientRecord(); - - r.token = token; - r.pendingResults = pendingResults; - r.pendingIntents = pendingNewIntents; - r.startsNotResumed = notResumed; - r.createdConfig = config; - - synchronized (mPackages) { - mRelaunchingActivities.add(r); - } - - queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges); + requestRelaunchActivity(token, pendingResults, pendingNewIntents, + configChanges, notResumed, config, true); } 

所以我想我可以使用scheduleRelaunchActivity而不是requestRelaunchActivity

而且我用反映写了他们:

 package me.piebridge.util; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import android.annotation.TargetApi; import android.app.Activity; import android.content.res.Configuration; import android.os.Build; import android.os.IBinder; public class GingerBreadUtil { private static Field scanField(Class<?> clazz, String... names) { for (String name : names) { Field field; try { field = clazz.getDeclaredField(name); field.setAccessible(true); return field; } catch (NoSuchFieldException e) { } try { field = clazz.getField(name); field.setAccessible(true); return field; } catch (NoSuchFieldException e) { } } return null; } public static void recreate(Activity activity) { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) { recreateHC(activity); } else { try { recreateGB(activity); } catch (InvocationTargetException e) { e.getTargetException().printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } } @TargetApi(Build.VERSION_CODES.HONEYCOMB) private static void recreateHC(Activity activity) { ((Activity) activity).recreate(); } private static void recreateGB(Activity activity) throws IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Field Activity$mToken = scanField(Activity.class, "mToken"); IBinder mToken = (IBinder) Activity$mToken.get(activity); Field Activity$mMainThread = scanField(Activity.class, "mMainThread"); Object mMainThread = Activity$mMainThread.get(activity); Field ActivityThread$mAppThread = scanField(mMainThread.getClass(), "mAppThread"); Object mAppThread = ActivityThread$mAppThread.get(mMainThread); Method method = mAppThread.getClass().getMethod("scheduleRelaunchActivity", IBinder.class, List.class, List.class, int.class, boolean.class, Configuration.class); method.invoke(mAppThread, mToken, null, null, 0, false, null); } } 

我正在使用这些代码来移植xposed框架。

如果这是你的问题,你可能应该实现另一种方法来填充你的活动视图。 而不是重新运行onCreate()你应该这样做onCreate()用一些参数调用你的填充方法。 当数据改变时,填充方法应该被另一个参数调用。

我解决这个问题的方式是使用Fragments 。 这些向后兼容,直到API 4通过使用支持库。

你用一个FrameLayout做一个“包装”布局。

例:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> 

然后你在任何时候都可以replaceFrameLayout来创build一个FragmentActivity。

例:

 public class SampleFragmentActivity extends FragmentActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.wrapper); // Check that the activity is using the layout version with // the fragment_container FrameLayout if (findViewById(R.id.fragment_container) != null) { // However, if we're being restored from a previous state, // then we don't need to do anything and should return or else // we could end up with overlapping fragments. if (savedInstanceState != null) { return; } updateLayout(); } } private void updateLayout() { Fragment fragment = new SampleFragment(); fragment.setArguments(getIntent().getExtras()); // replace original fragment by new fragment getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commit(); } 

在碎片你膨胀/replace你可以像你一样使用onStart和onCreateView通常会使用一个活动的onCreate。

例:

 public class SampleFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.yourActualLayout, container, false); } @Override public void onStart() { // do something with the components, or not! TextView text = (TextView) getActivity().findViewById(R.id.text1); super.onStart(); } } 

也许这是一个矫枉过正,但是: https : //stackoverflow.com/a/13173279/755804 (重新启动一个应用程序,提供本机库资源泄漏问题的解决方法。)

如果你想传递一个参数给onCreate(),那么你必须创build一个新的intent并添加额外的参数,并用它来调用StartActivity。 这是一个简单的例子,我用这种方式。

  String eczSabit = sa.getItem(position).getValue(); if(!Util.IsNullOrEmpty(eczSabit)){ sabit = Long.parseLong(eczSabit); Intent intent = new Intent(eczaneSegmentasyon.this,eczaneSegmentasyon.class); intent.putExtra("sabit", sabit); startActivity(intent); } 

如果你只是想重新做你的看法,我有同样的问题。 在onResume函数中试试把这个:

 mView = new AndroidPinballView(getApplication()); 

这也是在我的onCreate() ,所以把这个onResume为我工作:)