片段异步接口回调处理



我有一个Fragment,它通过一些助手Class与互联网进行一些通信,需要一个接口来处理异步回调,如下所示:

SomeInternetCommunicator.getResource(theResourceToGet, retrieverInterfaceInstance);

界面如下:

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

问题是,有时调用时间太长,用户已经导航到其他位置,并且对getResource进行调用的Fragment不再是当前运行的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()

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

谢谢!

有两种常见的方法来处理这种情况:

  1. 最好的方法是有一种方法从CCD_ 23中清除接口实例。类似于:

@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

最新更新