在恢复活动之前加载屏幕

时间:2016-03-23 07:10:24

标签: android android-fragments android-activity loading lifecycle

我希望在用户在恢复activity之前导航回activity时显示加载对话框 - 这可能吗?

以下是一些背景信息 - 首次启动活动时,会显示加载dialog,同时从文件加载某些缓存状态。对于较新的手机,这需要不到一秒的时间,但在较旧的型号上可能需要更长的时间,在任何情况下都无法在UI线程上运行。在用户导航回活动之前,垃圾收集器可以销毁缓存状态(或者可以杀死进程),这导致恢复活动的问题。具体来说,恢复的片段生命周期事件开始在活动的onCreate方法内部触发,并且它们在很大程度上依赖于缓存状态。理想情况下,应显示加载对话框,并且应延迟子fragments的生命周期事件,直到恢复缓存状态为止。

或者我可以在初始化每个片段/活动之前检查这些资源是否可用,但是如果使用了这种方法,那么恢复片段的状态可能需要延迟到onResume之后 - 我希望这导致问题正确恢复片段的父类使用的任何已保存的实例状态。框架是否提供了促进此功能的功能?

更新

下面提供了一个(设计的)示例 - 活动显示一个加载对话框,在该对话框后面会显示一个按钮以创建一个对话框片段。此时活动终止并重新启动;按预期,在加载对话框完成之前,将自动恢复测试对话框。问题是如何(或可以)延迟此过程,以便在恢复测试对话框之前完成加载对话框。

活动类:

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

测试对话框:

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

共享状态:

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

当运行以上内容时,最初会产生以下内容:

onCreate: start
onCreate: end
State.create: start
State.create: end
Loading finished
handleTestButton

终止并重新启动应用程序后,会生成以下内容:

onCreate: start
onAttach: state was null
onCreate: state was null
onCreate: end
State.create: start
onCreateView: state was null
State.create: end
Loading finished

1 个答案:

答案 0 :(得分:0)

您可以从您的onResume()方法移动将片段附加到活动的onCreate()方法的逻辑,因为它也是在第一次开始活动时调用的。

现在您的逻辑位于onResume(),您可以在ProgressDialod被调用时立即显示onResume。然后,您必须检查缓存数据何时完成加载。当它完全加载时,您可以关闭ProgressDialog并编写附加片段的逻辑。

我假设您可以在加载完成后获得一些回调,如果不是这样,您可能需要链接这些事件。