Antworten:
UPDATE : Android SDK 11 hat recreate()Aktivitäten eine Methode hinzugefügt .
Ich habe das getan, indem ich einfach die Absicht wiederverwendet habe, mit der die Aktivität gestartet wurde. Definieren Sie eine Absicht starterIntentin Ihrer Klasse und weisen Sie sie onCreate()mit zu starterIntent = getIntent();. Wenn Sie die Aktivität neu starten möchten, rufen Sie anfinish(); startActivity(starterIntent);
Es ist keine sehr elegante Lösung, aber es ist eine einfache Möglichkeit, Ihre Aktivität neu zu starten und sie zu zwingen, alles neu zu laden.
finish()sofort nach dem startActivity()aus genau diesem Grund anzurufen ...
finish();dann zuerst erreichtstartActivity(starterIntent);
Rufen Sie die Methode zum erneuten Erstellen der Aktivität auf.
recreate()aber jetzt sehe ich ein seltsames Problem, bei dem Optionsfelder beim Neuerstellen nicht zurückgesetzt werden, aber wenn finish(); startActivity(getIntent());dies der Fall ist, verwende ich dies jetzt und sehe, wie es in den nächsten Tagen oder Wochen funktioniert.
Wenn Sie hier einige Antworten kombinieren, können Sie Folgendes verwenden.
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();
}
}
}
Ich habe es ein bisschen getestet und es gibt einige Probleme:
startActivity(...); finish();existiert beim Aufrufen nur die App und die Aktivität wird nicht neu gestartet.super.recreate()verhält sich nicht so, als würde man die Aktivität vollständig neu erstellen. Dies entspricht dem Drehen des Geräts. Wenn Sie also Fragments haben, werden setRetainInstance(true)diese nicht neu erstellt. nur angehalten und wieder aufgenommen.Daher glaube ich derzeit nicht, dass es eine akzeptable Lösung gibt.
Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMBanstatt zu verwenden11
startActivity(getIntent());finish();zufinish();startActivity(getIntent());
Rufen recreate()Sie an Activity. Bei dieser Methode wird jedoch während der Neuerstellung der Aktivität ein blinkender schwarzer Bildschirm angezeigt.
finish();
startActivity(getIntent());
Hier gibt es keinen "blinkenden" schwarzen Bildschirm, aber Sie sehen einen Übergang zwischen der alten und der neuen Instanz mit einem nicht so angenehmen schwarzen Hintergrund. Wir können es besser machen.
Um dies zu beheben, können wir einen Aufruf hinzufügen an overridePendingTransition():
finish();
startActivity(getIntent());
overridePendingTransition(0, 0);
Auf Wiedersehen schwarzer Bildschirm, aber in meinem Fall sehe ich immer noch eine Art Übergang (eine Überblendanimation), diesmal auf einem farbigen Hintergrund. Dies liegt daran, dass Sie die aktuelle Instanz Ihrer Aktivität beenden, bevor die neue erstellt wird und vollständig sichtbar wird. Die Zwischenfarbe ist der Wert des windowBackgroundThemenattributs.
startActivity(getIntent());
finish();
Wenn Sie finish() danach anrufen, startActivity()wird der Standardübergang zwischen Aktivitäten verwendet, häufig mit einer kleinen Einschubanimation. Der Übergang ist aber noch sichtbar.
startActivity(getIntent());
finish();
overridePendingTransition(0, 0);
Für mich ist dies die beste Lösung, da die Aktivität ohne sichtbaren Übergang neu gestartet wird, als wäre nichts passiert.
Dies kann hilfreich sein, wenn Sie beispielsweise in Ihrer App eine Möglichkeit zum Ändern der Anzeigesprache unabhängig von der Systemsprache bereitstellen. In diesem Fall möchten Sie Ihre Aktivität wahrscheinlich immer dann ohne Übergang neu starten, wenn der Benutzer die Sprache Ihrer App ändert, damit der Sprachwechsel sofort angezeigt wird.
Wenn ich eine Aktivität neu starten muss, verwende ich folgenden Code. Obwohl es nicht empfohlen wird.
Intent intent = getIntent();
finish();
startActivity(intent);
Für API vor 11 können Sie recreate () nicht verwenden. Ich habe auf diese Weise gelöst:
Bundle temp_bundle = new Bundle();
onSaveInstanceState(temp_bundle);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("bundle", temp_bundle);
startActivity(intent);
finish();
und in 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
}
Nachdem recreateich nach dem Lebkuchengerät gesucht habe , möchte ich folgende Codes (für Lebkuchen) verwenden:
activity.mMainThread.mAppThread.scheduleRelaunchActivity(activity.mToken, null, null, 0, false, null);
Für diese Codes stammt es aus der Implementierung in einer höheren 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 hat keine requestRelaunchActivity, aber aus dem Diff habe ich folgendes gefunden:
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);
}
Also ich denke ich könnte scheduleRelaunchActivitystattdessen verwenden requestRelaunchActivity.
Und ich habe sie mit Reflect geschrieben:
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);
}
}
Ich verwende diese Codes für die Rückportierung von xposed Framework.
Build.VERSION_CODES.ECLAIR_MR1(v7). Es kann auch auf älteren Versionen funktionieren.
Wenn dies Ihr Problem ist, sollten Sie wahrscheinlich eine andere Methode implementieren, um die Ansicht in Ihrer Aktivität auszufüllen. Anstatt es erneut auszuführen onCreate(), sollten Sie es so machen, dass onCreate()Ihre Füllmethode mit einem Argument aufgerufen wird. Wenn sich die Daten ändern, sollte die Füllmethode mit einem anderen Argument aufgerufen werden.
Ich habe es so gelöst, indem ich Fragmente verwendet habe . Diese sind bis API 4 mithilfe der Support-Bibliothek abwärtskompatibel.
Sie erstellen ein "Wrapper" -Layout mit einem FrameLayout.
Beispiel:
<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>
Anschließend erstellen Sie eine FragmentActivity, in der Sie das FrameLayout jederzeit ersetzen können.
Beispiel:
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();
}
In dem Fragment, das Sie aufblasen / ersetzen, können Sie onStart und onCreateView so verwenden, wie Sie normalerweise das onCreate einer Aktivität verwenden würden.
Beispiel:
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();
}
}
Ich habe einmal eine Test-App erstellt, die die Datenbankdatei mithilfe des Firebase-Cloud-Speichers hochlädt, löscht und dann erneut herunterlädt. Um die Daten in der Datenbank anzuzeigen, war der folgende Code die einzige Lösung, die ich gefunden habe. Weder recreate()noch finish()in diesem Fall funktioniert.
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
System.exit(0);
Ich habe herausgefunden, wie Sie Ihr Fragment am besten aktualisieren können, wenn sich Daten ändern
Wenn Sie eine Schaltfläche "Suchen" haben, müssen Sie Ihre ARRAY-Liste innerhalb der Schaltfläche initialisieren
mSearchBtn.setOnClickListener (neuer View.OnClickListener () {
@Override public void onClick (View v) {
mList = new ArrayList<Node>();
firebaseSearchQuery.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
Node p = dataSnapshot1.getValue(Node .class);
mList.add(p);
}
YourAdapter = new NodeAdapter(getActivity(), mList);
mRecyclerView.setAdapter(YourAdapter );
}
Wenn Sie einen Parameter an onCreate () übergeben möchten, müssen Sie eine neue Absicht mit dem Hinzufügen von extra erstellen und damit StartActivity aufrufen. Hier ist ein einfaches Beispiel, das ich auf diese Weise gemacht habe.
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);
}
Wenn Sie nur versuchen, Ihre Ansicht zu wiederholen, hatte ich genau das gleiche Problem. onResumeVersuchen Sie in der Funktion Folgendes:
mView = new AndroidPinballView(getApplication());
Das war auch in meinem onCreate(), also hat das onResumefür mich funktioniert :)