【问题标题】:Toast in OnPostExecute() once the fragment changes片段更改后在 OnPostExecute() 中吐司
【发布时间】:2019-05-30 08:39:44
【问题描述】:

我的 Activity 中有两个片段:Fragment_A 和 Fragment_B。

在片段 A 中,我创建了一个 AsyncTask(当用户“滑动刷新”屏幕时)。在这个任务的onPostExecute() 中,我想显示一个 Toast :

private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
    private Exception mLastError = null;

    MakeRequestTask() {
        //Some stuff
    }

    @Override
    protected List<String> doInBackground(Void... params) {
        //Some stuff
    }

    @Override
    protected void onPreExecute() {
        //Some stuff
    }

    @Override
    protected void onPostExecute(List<String> output) {
        swipeRefreshLayout.setRefreshing(false);
        Toast.makeText(getActivity(), "TO_DISPLAY", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onCancelled() {
        swipeRefreshLayout.setRefreshing(false);
        //Some stuff
    }
}


如果用户在 AsyncTask 完成之前从 Fragment_A 更改为 Fragment_B,我会崩溃:

java.lang.IllegalStateException: Fragment Fragment_A 未附加到上下文。

我知道如何避免崩溃(通过添加条件 isAdded()),但我希望无论哪个 Fragment 在我的 Activity 上显示/激活,我都希望显示我的 Toast。

【问题讨论】:

  • 不是通过调用 getActivity() 来获取 onPostExecute 中的活动,而是在构造函数中传递活动或上下文。这样,asyncTask 就已经拥有了它需要的一切。
  • 也不工作。一旦片段消失,上下文就会丢失。仅供参考,在 Fragment_A 中声明了“私有类 MakeRequestTask”。
  • 检查我的答案并尝试并告诉我

标签: android


【解决方案1】:

首先我想建议您,请将您的 MakeRequestTask 内部类设为静态,因为这可能是内存泄漏。 对于您的问题,您需要将上下文传递给如下类:

    private static class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
        private Exception mLastError = null;
        private WeakReference<Context> weakReference;

        MakeRequestTask(Context context) {
            //Some stuff
            weakReference = new WeakReference<>(context);
        }

        @Override
        protected List<String> doInBackground(Void... params) {
            //Some stuff
        }

        @Override
        protected void onPreExecute() {
            //Some stuff
        }

        @Override
        protected void onPostExecute(List<String> output) {
// swipe layout will not be shown if fragment is not visible or destroyed
            if (isFragmentVisible) {
                swipeRefreshLayout.setRefreshing(false);
            }
// toast will be shown no matter what fragment is visible
            if (weakReference != null) {
                Context context = weakReference.get();
                if (context != null) {
                    Toast.makeText(context, "TO_DISPLAY", Toast.LENGTH_SHORT).show();
                }
            }
        }

        @Override
        protected void onCancelled() {
            if (isFragmentVisible) {
                swipeRefreshLayout.setRefreshing(false);
            }
            //Some stuff
        }
    }

【讨论】:

    【解决方案2】:

    试试这个方法 在Fragment_A中声明一个布尔值

    private boolean isFragmentVisible=false;
    

    Fragment_A类中

    在此onCreateView() 中将此布尔值设为真Fragment_A

      @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        view = inflater.inflate(R.layout.lyourlayout, container, false);
        isFragmentVisible = true;
        return view;
    }
    

    并将此片段 A 的 onDestroyView() 中的布尔值设为 false

    @Override
        public void onDestroyView() {
            super.onDestroyView();
            isFragmentVisible = false;
        }
    

    终于像这样在Fragment_A的Asyntask中使用了

    private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
        private Exception mLastError = null;
    
        MakeRequestTask() {
            //Some stuff
        }
    
        @Override
        protected List<String> doInBackground(Void... params) {
            //Some stuff
        }
    
        @Override
        protected void onPreExecute() {
            //Some stuff
        }
    
        @Override
        protected void onPostExecute(List<String> output) {
    // swipe layout will not be shown if fragment is not visible or destroyed
            if(isFragmentVisible){
                  swipeRefreshLayout.setRefreshing(false);
                }
    // toast will be shown no matter what fragment is visible
             Toast.makeText(getActivity(), "TO_DISPLAY", Toast.LENGTH_SHORT).show();            
            }
    
        @Override
        protected void onCancelled() {
           if(isFragmentVisible){
                  swipeRefreshLayout.setRefreshing(false);
                }
            //Some stuff
        }
    }
    

    【讨论】:

      【解决方案3】:

      或者您可以在onPostExecute 方法中使用和interfaceEventBus,并在活动中显示Toast

      @Override
          protected void onPostExecute(List<String> output) {
              swipeRefreshLayout.setRefreshing(false);
              activityContractInterface.showToast()
              }
          }
      

      在你的活动中:

      @Override
      public void showToast(){
           Toast.makeText(getActivity(), "TO_DISPLAY", Toast.LENGTH_SHORT).show();
      }
      

      或者 EventBus 方法:

      @Override
              protected void onPostExecute(List<String> output) {
                  swipeRefreshLayout.setRefreshing(false);
                  EventBus.getDefault().post(new ShowToastEvent()) 
      //just create an empty class, hope you know what EventBus is
                  }
      

      在你的活动中:

      @Subscribe(threadMode = ThreadMode.Main){
       Toast.makeText(getActivity(), "TO_DISPLAY", Toast.LENGTH_SHORT).show();
      }
      

      EventBusLibrary

      【讨论】:

        猜你喜欢
        • 2020-07-22
        • 2014-06-28
        • 2018-09-20
        • 2015-01-04
        • 1970-01-01
        • 2016-08-31
        • 2018-09-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多