【问题标题】:Fragment asynchronous Interface callback handling片段异步接口回调处理
【发布时间】:2016-08-04 08:33:05
【问题描述】:

我有一个Fragment,它通过一些帮助器Class 与互联网进行一些通信,它需要一个接口来处理这样的异步回调:

SomeInternetCommunicator.getResource(theResourceToGet, retrieverInterfaceInstance);

界面如下:

public interface SomeInternetCommunicator {
     void onResourceRetrieveSuccess(SomeResource resource);
     void onResourceRetrieveFailed(CommunicatorException e);
}

问题是,有时调用时间过长,用户已经导航到其他地方,并且调用 getResourceFragment 不再是当前正在运行的 Activity 的一部分(不显示,不在回栈)。这会导致很多问题,因为这个孤儿 Fragment 仍在尝试对回调做出反应,即使它不再是 Activity 的一部分。例如,getContext() 返回 null。

现在我在Fragment 上的解决方法如下所示:

SomeInternetCommunicator flocktrackerTrackerRetrieverInterface = new SomeInternetCommunicator() {
            @Override
            public void onResourceRetrieveSuccess(SomeResource resource) {
                if(isVisible()){
                    doRetrievalPostProcessing(resource);
                }
            }

            @Override
            void onResourceRetrieveFailed(CommunicatorException e) {
                if(isVisible()){
                    doExceptionHandling();
                }
            }
        };

使用isVisible() 有效,因为这样可以确保片段仍然在前台,是Activity 的一部分并准备好进行处理。但是,这并不能帮助我解决Fragment 不可见但仍然是当前Activity 的一部分的情况,这限制了我在显示之前加载Fragment 的可能性。 (Activity 在后台,FragmentBackstack 上,FragmentViewPager 加载)。

在我进行后处理之前,有没有更好的方法来确保Fragment 仍然在当前Activity 的范围内?也许检查isAdded()

This question 似乎解释了一个更广泛但相关的情况,但它没有答案。

谢谢!

【问题讨论】:

  • 是的 isAdded() 是正确的。如果您想在添加和删除时执行更多操作,请覆盖 onAttach() 和 onDetach()。

标签: android android-fragments asynchronous


【解决方案1】:

这种情况有两种常用的方法:

  1. 最好的方法是从SomeInternetCommunicator 中清除接口实例。比如:

.

@Override public void onDestroyView(){
   SomeInternetCommunicator.removeMe(this);
}
  1. 如果选项 (1) 不可行,因为 SomeInternetCommunicator 是一个编码不佳的库,您可以通过创建一个单独的类来实现接口来强制选项 1 成为可能。

.

public class SomeInternetCommunicatorInterceptor implements SomeInternetCommunicatorInterface {

    private SomeInternetCommunicatorInterface listener;

    public void setListener(SomeInternetCommunicatorInterface listener){
        this.listener=listener;
    }

    @Override
    public void onResourceRetrieveSuccess(SomeResource resource){
         if(listener != null){
              listener.onResourceRetrieveSuccess(resource);
         }
    }
    @Override
    public void onResourceRetrieveFailed(CommunicatorException e){
         if(listener != null){
              listener.onResourceRetrieveFailed(e);
         }
    }
}

然后在您的片段上,您将这个新类用作:

private SomeInternetCommunicatorInterceptor interceptor;

public void onCreateView(....){

... your code

   interceptor = new SomeInternetCommunicatorInterceptor();

}

onStart(){
   interceptor.setListener(this);
}

onStop(){
   interceptor.setListener(null);
}

public void onDestroyView(){
   interceptor = null;
   super.onDestroyView();
}

非常重要:

如果您将SomeInternetCommunicatorInterceptor 设为片段的内部类,则必须将其设为static class

【讨论】:

  • 谢谢!,SomeInternetCommunicator 确实是一个编码不佳的库,但它是我自己编码的,所以我可以做你建议的更改。
  • 使用类似的方法,如果片段被分离或活动被破坏,是否可以“缓存”事件,并在重新创建活动/附加片段后立即使用该事件?例如,在我的应用程序中,我可以执行在某些情况下可能需要一些时间的网络请求。当成功或失败时,我用Snackbar 通知用户,但如果活动被破坏(后退按钮、垃圾收集等),这是不可能的。为了弥补分离的片段,我有一个WeakReference 到android.R.id.content View 用于Snackbar。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-10
  • 2016-12-13
  • 2016-08-08
  • 1970-01-01
  • 2021-04-16
  • 2021-06-17
  • 2019-02-12
相关资源
最近更新 更多