如何处理处理程序的消息时,活动/片段被暂停 [英] How to handle Handler messages when activity/fragment is paused

查看:134
本文介绍了如何处理处理程序的消息时,活动/片段被暂停的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的其他发布

基本上,我有一个消息处理程序我的片段接收了一堆的消息,可能导​​致对话框是的解雇或显示。

Basically I have a message Handler in my Fragment which receives a bunch of messages that can result in dialogs being dismissed or shown.

当应用程序放入后台,我得到一个的onPause 但后来还是把我的信息来通过为人们所期望的。但是,因为我使用的片段,我不能只辞退并显示对话框因为这将导致 IllegalStateException异常

When the app is put into the background I get an onPause but then still get my messages coming through as one would expect. However, because I'm using fragments I can't just dismiss and show dialogs as that will result in an IllegalStateException.

我不能只辞退或取消使国家损失。

I can't just dismiss or cancel allowing state loss.

既然我有一个处理程序我不知道是否有推荐的方法,以 我应该如何处理邮件,而处于暂停状态。

Given that I have a Handler I'm wondering whether there is a recommended approach as to how I should handle messages while in a paused state.

一个可能的解决方案,我正在考虑是记录通过,同时传来的消息暂停和发挥他们回到一个 onResume 。这是有点不尽人意,我想,一定有什么东西在框架来处理这个更优雅。

One possible solution I'm considering is to record the messages coming through while paused and play them back on an onResume. This is somewhat unsatisfactory and I'm thinking that there must be something in the framework to handle this more elegantly.

在此先感谢。彼得。

推荐答案

虽然Android操作系统不会出现有一个是足够解决你的问题,我相信这个模式确实提供了一个相对容易实现的解决方法的机制。

Although the Android operating system does not appear to have a mechanism that sufficiently addresses your problem I believe this pattern does provide a relatively simple to implement workaround.

下面的类是围绕android.os.Handler一个包装,缓冲了当一个活动被暂停的消息,并播放他们回来的简历。

The following class is a wrapper around android.os.Handler that buffers up messages when an activity is paused and plays them back on resume.

确保任何code,你有哪些异步改变一个片段的状态(如提交,解雇)只从处理的消息调用。

Ensure any code that you have which asynchronously changes a fragment state (e.g. commit, dismiss) is only called from a message in the handler.

从PauseHandler类派生的处理程序。

Derive your handler from the PauseHandler class.

每当你的活动收到的onPause()调用PauseHandler.pause()和onResume()调用PauseHandler.resume()。

Whenever your activity receives an onPause() call PauseHandler.pause() and for onResume() call PauseHandler.resume().

替换您的实现处理程序的handleMessage()用而processMessage(的)。

Replace your implementation of the Handler handleMessage() with processMessage().

提供一个简单的实现storeMessage(),它总是返回

Provide a simple implementation of storeMessage() which always returns true.

/**
 * Message Handler class that supports buffering up of messages when the
 * activity is paused i.e. in the background.
 */
public abstract class PauseHandler extends Handler {

    /**
     * Message Queue Buffer
     */
    final Vector<Message> messageQueueBuffer = new Vector<Message>();

    /**
     * Flag indicating the pause state
     */
    private boolean paused;

    /**
     * Resume the handler
     */
    final public void resume() {
        paused = false;

        while (messageQueueBuffer.size() > 0) {
            final Message msg = messageQueueBuffer.elementAt(0);
            messageQueueBuffer.removeElementAt(0);
            sendMessage(msg);
        }
    }

    /**
     * Pause the handler
     */
    final public void pause() {
        paused = true;
    }

    /**
     * Notification that the message is about to be stored as the activity is
     * paused. If not handled the message will be saved and replayed when the
     * activity resumes.
     * 
     * @param message
     *            the message which optional can be handled
     * @return true if the message is to be stored
     */
    protected abstract boolean storeMessage(Message message);

    /**
     * Notification message to be processed. This will either be directly from
     * handleMessage or played back from a saved message when the activity was
     * paused.
     * 
     * @param message
     *            the message to be handled
     */
    protected abstract void processMessage(Message message);

    /** {@inheritDoc} */
    @Override
    final public void handleMessage(Message msg) {
        if (paused) {
            if (storeMessage(msg)) {
                Message msgCopy = new Message();
                msgCopy.copyFrom(msg);
                messageQueueBuffer.add(msgCopy);
            }
        } else {
            processMessage(msg);
        }
    }
}

下面是如何的PausedHandler类可用于一个简单的例子。

Below is a simple example of how the PausedHandler class can be used.

在一个按键延迟的消息发送给处理程序的点击。

On the click of a button a delayed message is sent to the handler.

在处理接收到的信息(UI线程),它会显示一个DialogFragment。

When the handler receives the message (on the UI thread) it displays a DialogFragment.

如果没有被使用一个IllegalStateException的PausedHandler类将被显示,如果home键是$ P $经过pressed pssing测试按钮启动对话框。

If the PausedHandler class was not being used an IllegalStateException would be shown if the home button was pressed after pressing the test button to launch the dialog.

public class FragmentTestActivity extends Activity {

    /**
     * Used for "what" parameter to handler messages
     */
    final static int MSG_WHAT = ('F' << 16) + ('T' << 8) + 'A';
    final static int MSG_SHOW_DIALOG = 1;

    int value = 1;

    final static class State extends Fragment {

        static final String TAG = "State";
        /**
         * Handler for this activity
         */
        public ConcreteTestHandler handler = new ConcreteTestHandler();

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRetainInstance(true);            
        }

        @Override
        public void onResume() {
            super.onResume();

            handler.setActivity(getActivity());
            handler.resume();
        }

        @Override
        public void onPause() {
            super.onPause();

            handler.pause();
        }

        public void onDestroy() {
            super.onDestroy();
            handler.setActivity(null);
        }
    }

    /**
     * 2 second delay
     */
    final static int DELAY = 2000;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        if (savedInstanceState == null) {
            final Fragment state = new State();
            final FragmentManager fm = getFragmentManager();
            final FragmentTransaction ft = fm.beginTransaction();
            ft.add(state, State.TAG);
            ft.commit();
        }

        final Button button = (Button) findViewById(R.id.popup);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                final FragmentManager fm = getFragmentManager();
                State fragment = (State) fm.findFragmentByTag(State.TAG);
                if (fragment != null) {
                    // Send a message with a delay onto the message looper
                    fragment.handler.sendMessageDelayed(
                            fragment.handler.obtainMessage(MSG_WHAT, MSG_SHOW_DIALOG, value++),
                            DELAY);
                }
            }
        });
    }

    public void onSaveInstanceState(Bundle bundle) {
        super.onSaveInstanceState(bundle);
    }

    /**
     * Simple test dialog fragment
     */
    public static class TestDialog extends DialogFragment {

        int value;

        /**
         * Fragment Tag
         */
        final static String TAG = "TestDialog";

        public TestDialog() {
        }

        public TestDialog(int value) {
            this.value = value;
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            final View inflatedView = inflater.inflate(R.layout.dialog, container, false);
            TextView text = (TextView) inflatedView.findViewById(R.id.count);
            text.setText(getString(R.string.count, value));
            return inflatedView;
        }
    }

    /**
     * Message Handler class that supports buffering up of messages when the
     * activity is paused i.e. in the background.
     */
    static class ConcreteTestHandler extends PauseHandler {

        /**
         * Activity instance
         */
        protected Activity activity;

        /**
         * Set the activity associated with the handler
         * 
         * @param activity
         *            the activity to set
         */
        final void setActivity(Activity activity) {
            this.activity = activity;
        }

        @Override
        final protected boolean storeMessage(Message message) {
            // All messages are stored by default
            return true;
        };

        @Override
        final protected void processMessage(Message msg) {

            final Activity activity = this.activity;
            if (activity != null) {
                switch (msg.what) {

                case MSG_WHAT:
                    switch (msg.arg1) {
                    case MSG_SHOW_DIALOG:
                        final FragmentManager fm = activity.getFragmentManager();
                        final TestDialog dialog = new TestDialog(msg.arg2);

                        // We are on the UI thread so display the dialog
                        // fragment
                        dialog.show(fm, TestDialog.TAG);
                        break;
                    }
                    break;
                }
            }
        }
    }
}

我添加了一个storeMessage()方法,以防PausedHandler类中的任何信息,应立即即使当活动被暂停处理。如果消息被处理,然后假应返回,该消息将被丢弃。

I've added a storeMessage() method to the PausedHandler class in case any messages should be processed immediately even when the activity is paused. If a message is handled then false should be returned and the message will be discarded.

这篇关于如何处理处理程序的消息时,活动/片段被暂停的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆