我正在编写一个应用程序,其中我在ViewPager中有不同的片段。在每个片段中,我使用几个AsyncTask从Web服务器获取数据。一些片段需要调用相同的AsynTask(服务),但如果其中一个已经调用它,因为服务需要一段时间来响应,我想防止调用它,但我想让AsyncTask发送导致所有称之为碎片的碎片。当用户更新片段时,我还需要更新所有片段中的de数据(SwipeToRefresh即)。我今天拥有的函数是一个函数,我验证服务是否已被调用,如果不是这样,保存一个标志来指示服务被调用,并使用AsyncTask调用服务,该函数接收回调接口以发送结果是请求Fragmnet,如果在另一方面,服务已被调用,则将Callback添加到Callback列表,稍后在AsyncTask.onPostExecute中遍历该列表以将resull发送到所有fragmnet。
最大的问题是,当我发出多个请求时,就像用户在一段时间后打开应用程序一样,导致内存泄漏(GC工作太多而应用程序冻结)并且应用程序终止。它也没有解决在一次调用中更新所有片段的问题。
这是我之前提到过的代码(只是一个例子):
public class Test {
private static List<Integer> calledServices = new ArrayList<>();
private static Map<Integer, List<Callback>> callbacksMap = new HashMap<>();
public static void call(int serviceId, Callback callback) {
if (!hasBeenCalled(serviceId)) {
calledServices.add(serviceId); //saves flag
ServiceAsyncTask task = new ServiceAsyncTask(serviceId, callback);
task.execute();
} else {
callback.onPreExecute();
if (callbacksMap.containsKey(serviceId)) {
callbacksMap.get(serviceId).add(callback);
} else {
List<Callback> callbacks = new ArrayList<>();
callbacks.add(callback);
callbacksMap.put(serviceId, callbacks);
}
}
}
private static boolean hasBeenCalled(int serviceId) {
return calledServices.contains(serviceId);
}
interface Callback {
void onPreExecute();
void onPostExecute(Object object);
}
static class ServiceAsyncTask extends AsyncTask<Object, Object, Object> {
private final int serviceId;
private final Callback mCallback;
ServiceAsyncTask(int serviceId, Callback callback) {
this.serviceId = serviceId;
this.mCallback = callback;
}
@Override
protected void onPreExecute() {
mCallback.onPreExecute();
}
Object doInBackground(Object... params) {
return WebService.call(serviceId);
}
@Override
protected void onPostExecute(Object o) {
mCallback.onPostExecute(o);
if (!callbacksMap.containsKey(serviceId)) return;
for (Callback callback : callbacksMap.get(serviceId)) {
callback.onPostExecute(o);
}
callbacksMap.remove(serviceId);
calledServices.remove(serviceId);
}
}
}
我希望你能帮助我,并为我可能做过的任何拼写错误或语法错误道歉。
答案 0 :(得分:0)
当前片段可见时进行API调用。
例如,
private boolean hasLoadedOnce= false;
@Override
public void setUserVisibleHint(boolean isFragmentVisible) {
super.setUserVisibleHint(true);
if (this.isVisible()) {
// we check that the fragment is becoming visible
if (isFragmentVisible && !hasLoadedOnce) {
new ServiceAsyncTask().execute();
hasLoadedOnce = true;
}
}
}
我希望,通过这种方式,你可以在内部管理api调用并轻松更新。
答案 1 :(得分:0)
我有类似你的问题。我还有一个回调,它由想要使用数据的每个视图/片段实现。然后我有一个asynctask加载数据。当我得到响应时,我将对象保存到一个管理器类中,该类包括我必须通知视图更新的回调列表。因此,实现回调的所有视图/片段都必须自己在管理器上注册。
代码示例: Example
答案 2 :(得分:0)
您可以在Java(1.5或更高版本)中使用枚举,如下所示:-
enum Tasks {
task1, task2
}
并在这样的接口方法中传递'Tasks'类型的参数:-
interface Callback {
void onPreExecute(Tasks task);
void onPostExecute(Tasks task, Object object);
}
并像这样使用它:-
callback.onPreExecute(Tasks.task1); or callback.onPostExecute(Tasks.task1, object);