Ich möchte einen Ladedialog anzeigen, wenn der Benutzer zurück zu meinem activity
vor der Wiederaufnahme der activity
navigiert - ist das möglich?Laden des Bildschirms vor dem Fortsetzen einer Aktivität
Hier ist ein Hintergrund - wenn die Aktivität zum ersten Mal gestartet wird, wird ein Ladevorgang dialog
angezeigt, während ein Cache-Status aus einer Datei geladen wird. Dies dauert bei neueren Telefonen weniger als eine Sekunde, kann jedoch bei älteren Modellen länger dauern und ist für die Ausführung auf dem UI-Thread in jedem Fall zu lang. Der zwischengespeicherte Status kann durch den Garbage Collector zerstört werden (oder der Prozess kann abgebrochen werden), bevor der Benutzer zu der Aktivität zurück navigiert, was zu Problemen beim Wiederaufnehmen der Aktivität führt. Im Speziellen beginnen wiederhergestellte Fragmentlebenszyklusereignisse innerhalb der onCreate
-Methode der Aktivität und hängen stark vom zwischengespeicherten Status ab. Im Idealfall sollte ein Ladedialog angezeigt werden und die Lebenszyklusereignisse von Kind fragments
sollten verzögert werden, bis der zwischengespeicherte Zustand wiederhergestellt ist.
Alternativ könnte ich überprüfen, ob diese Ressourcen vor der Initialisierung jedes Fragments/Aktivität verfügbar sind, aber wenn dieser Ansatz verwendet würde, müsste die Wiederherstellung des Fragmentstatus wahrscheinlich erst nach onResume
verzögert werden - das würde ich erwarten Bei Problemen, die den von den Elternklassen des Fragments verwendeten Status der gespeicherten Instanz wiederherstellen. Bietet das Framework Möglichkeiten, dies zu erleichtern?
UPDATE
A (contrived) Beispiel ist unten angegeben - die Tätigkeit zeigt einen Ladedialog woraufhin eine Schaltfläche angezeigt wird, ein Dialog-Fragment zu erzeugen. An diesem Punkt wird die Aktivität beendet und neu gestartet; Wie erwartet wird der Testdialog automatisch wiederhergestellt, bevor der Ladedialog abgeschlossen ist. Die Frage ist, wie kann dieser Prozess (oder kann) verzögert werden, so dass der Ladedialog abgeschlossen wird, bevor der Testdialog wiederhergestellt wird.
Die Aktivitätsklasse:
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private ProgressDialog dialog_ = null;
private Button button_ = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.v(TAG, "onCreate: start");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button_ = (Button)findViewById(R.id.testButton);
// A loading dialog is displayed when the activity is created if the cached state is null
if (State.get() == null) {
// Using a button here instead of some content fragment for convenience
button_.setVisibility(View.GONE);
// Create a loading dialog
dialog_ = new ProgressDialog(this);
dialog_.setMessage("Loading...");
dialog_.setIndeterminate(true);
dialog_.show();
// Create the cached state in a background thread
new Thread(new Runnable() {
@Override
public void run() {
Log.v(TAG, "State.create: start");
State.create(MainActivity.this);
Log.v(TAG, "State.create: end");
runOnUiThread(new Runnable() {
@Override
public void run() {
if (dialog_ != null) {
dialog_.dismiss();
dialog_ = null;
}
// When the loading dialog is finished the content fragment is loaded;
// here the button is merely displayed. Ideally the life-cycle events
// in TestDialog should not be called until after this point.
button_.setVisibility(View.VISIBLE);
Log.v(TAG, "Loading finished");
}
});
}
}).start();
}
Log.v(TAG, "onCreate: end");
}
public void handleTestButton (final View view) {
Log.v(TAG, "handleTestButton");
// A dialog fragment is added here; the framework will automatically restore the fragment
// if the activity is terminated and restored.
new TestDialog().show(getSupportFragmentManager(), null);
}
}
Der Test-Dialog:
public class TestDialog extends DialogFragment {
private static final String TAG = TestDialog.class.getSimpleName();
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (State.get() == null)
Log.w(TAG, "onAttach: state was null");
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (State.get() == null)
Log.w(TAG, "onCreate: state was null");
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (State.get() == null)
Log.w(TAG, "onCreateView: state was null");
return inflater.inflate(R.layout.test_dialog, container, false);
}
}
Der Shared-Zustand:
public class State {
private static Object state_ = null;
// A long running process is performed on a background thread; locking omitted for clarity
public static void create (final Context context) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
state_ = new Object();
}
// Fragment life-cycle events require the cached state
public static Object get() {
return state_;
}
}
Wenn die oben folgend ausgeführt wird anfänglich hergestellt wird:
onCreate: start
onCreate: end
State.create: start
State.create: end
Loading finished
handleTestButton
Nach Beendigung und Neubelebung der App die folgenden hergestellt:
onCreate: start
onAttach: state was null
onCreate: state was null
onCreate: end
State.create: start
onCreateView: state was null
State.create: end
Loading finished
Die gespeicherten Fragmente werden in der onCreate-Methode der Aktivität vor jeder offenen Aktion (d. H. Nicht als Reaktion auf eine explizite Fragmenttransaktion oder ähnliches) wiederhergestellt (dh ihre Lebenszyklusereignisse beginnen zu feuern). Könnten Sie das erklären? –
Ich dachte, dass Sie die Fragmente explizit anhängen, wenn es automatisch passiert, dann wird es wahrscheinlich nicht funktionieren. Wenn Sie den Code posten können, könnte ich einen Blick darauf werfen. –
Es passiert automatisch; 'onCreate' in' FragmentActivity' ruft beispielsweise die 'onAttach' und' onCreate' Methoden des Fragments auf. Das Projekt ist viel zu groß, um es zu posten, aber ich werde versuchen, ein motivierendes Beispielprojekt zu entwickeln, um meine Frage zu klären. –