【问题标题】:Volley response handler dismissing a dialog fragment after an orientation changeVolley 响应处理程序在方向更改后解除对话框片段
【发布时间】:2016-10-27 20:11:44
【问题描述】:

当我的Activity 发出Volley 请求时,我会显示一个带有对话框片段的对话框。在Activity 的非静态内部类的响应处理程序中,我关闭对话框片段:

@Override
public void onResponse(String response) {
    MyActivity.this.takeAwayTheDialog();
}

除非我旋转设备,否则一切正常。如果在方向更改完成后返回响应,则MyActivity.this 已被销毁。

可能的解决方案包括:

  1. 在方向改变之前取消请求
  2. 使用单独的保留片段来处理网络请求

但它们看起来并不令人满意。我想要一个解决方案,允许系统为我处理方向,以便重新创建活动并加载正确的资源。任何人都可以对上述两种解决方案发表评论或提出其他建议吗?谢谢。

【问题讨论】:

  • 在特定活动的清单中,您可以定义`android:configChanges="orientation"`。因此,它不会重新启动活动。
  • 您可以轻松地覆盖onOrientationChanged 函数,以便在更改方向后进行必要的更改。您可能会在停止上一个 volley 请求后再次调用该请求。
  • @NigamPatro ,请避免使用android:configChanges="orientation"。从 docs 开始,应避免使用此属性并仅将其用作最后的手段,请查看this 答案以了解详细信息。
  • 只是为了确定,您是否使用FragmentManager 来显示对话框?这样它就可以在配置更改后继续存在。
  • @Mike。在开始网络请求之前,我会显示一个带有myDialogFragment.show(getFragmentManager(), TAG); 的对话框。我在支持片段中称其为,但我提到我在问题中使用了Activity。我的坏...

标签: android android-fragments android-activity orientation android-volley


【解决方案1】:

由于没有人回答这个问题,我会在你的解决方案中写下我的意见:

  1. 在方向更改之前取消请求(可能在您的活动的onPause() 中)并在方向更改之后重新启动它(可能在onResume() 中)可能是一个快速有效的解决方案,但它可能最终您发送向服务器请求两次。

    这通常不是问题,但如果请求是例如注册用户的POST 请求,则可能导致用户在方向更改后收到用户名已经存在的错误(因为第一个活动已成功将其注册到服务器,第二个活动正在尝试再次注册他/她)。

    如果发送两次请求对你来说不是问题,这个解决方案效果很好,因为 Volley 可以透明地为你缓存第一个请求的响应(如果服务器发送正确的 headers),第二个请求将得到响应就好像你有一个超快速的连接。 . .

  2. 使用保留的无头片段,从其中启动 Volley 请求,并回调到您当前的活动中效果很好,我认为它确实 允许系统为您处理方向,以便重新创建活动并加载正确的资源,然后当前活动获得响应并将其显示给用户。

    在这个解决方案中我能想到的唯一缺点是它需要编写大量样板代码,以下是如何使用这种方法来显示和隐藏对话框。

    public class MainActivity extends AppCompatActivity{
    
        public static class MainActivityHeadlessFragment extends Fragment {
    
            private MainActivity mActivity;
            public MainActivityHeadlessFragment() {
                // Required empty public constructor
            }
    
    
    
            @Override
            public void onCreate(@Nullable Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setRetainInstance(true);
            }
    
            public void ShowDialog() {
                DialogFragment newFragment = SampleDialogFragment.newInstance();
                newFragment.show(mActivity.getSupportFragmentManager(), "sample_dialog_tag");
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        Fragment f = mActivity.getSupportFragmentManager().findFragmentByTag("sample_dialog_tag");
                        if(f!= null){
                            DialogFragment df = (DialogFragment) f;
                            df.dismiss();
                        }
                    }
                }, 5000);
            }
    
            @Override
            public void onAttach(Context context) {
                super.onAttach(context);
                if (context instanceof MainActivity) {
                    mActivity= (MainActivity) context;
                } else {
                    throw new RuntimeException(context.toString()
                            + " MainActivityHeadlessFragment can only be used with MainActivity");
                }
            }
    
            @Override
            public void onDetach() {
                super.onDetach();
                mActivity= null;
            }
        }
    
        private MainActivityHeadlessFragment mDataFragment;
        private MainFragment mFragment;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            FragmentManager fm = getSupportFragmentManager();
            mDataFragment = (MainActivityHeadlessFragment) fm.findFragmentByTag("data_fragment");
    
            // If the Fragment is non-null, then it is currently being
            // retained across a configuration change.
            if (mDataFragment == null) {
                mDataFragment = new MainActivityHeadlessFragment();
                fm.beginTransaction().add(mDataFragment, "data_fragment").commit();
            }
        }
    
    
    
        public void ShowDialog(View v){
            mDataFragment.ShowDialog();
        }
    }
    

    为简单起见,我将 Volley 请求替换为 new Handler().postDelayed(),但想法应该相同。 . .

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-02
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    相关资源
    最近更新 更多