我的应用程序使用volley进行webservice调用,以便每10秒更新一次recyclerView。除了内存使用量持续增加10秒,直到它达到最大堆大小。然后GC开始完成它的工作,但内存使用率并没有像开始那样回落。 使用Eclipse MAT或Android Studio分析器任务,我无法在代码中找到单个泄漏。
我想知道如果我的代码中有泄漏的嫌疑人。任何帮助将不胜感激。
下面我有3个班级:
EventService
每10秒钟使用MainActivity
向sendBroadcast()
发送一条消息。
MainActiviy
将使用EventService
从BroadcastReceiver
收到消息,并在其update
Fragment
次操作
EventListFragment
位于MainActivity
内,包含RecyclerView
,需要更新。
这是我的EventService
:
public class EventService extends Service {
private volatile boolean isCanceled = false;
public static final String KEY_MESSAGE = "connection";
public EventService() {}
@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
Runnable r = new Runnable() {
@Override
public void run() {
while (!isCanceled) {
try {
Intent i = new Intent("android.intent.action.MAIN");
AppController.getInstance().cancelPendingRequests("json_obj_req");
i.putExtra(KEY_MESSAGE, MESSAGE);
sendBroadcast(i);
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread eventThread = new Thread(r);
eventThread.start();
return Service.START_STICKY;
}
@Override
public void onDestroy() {
isCanceled = true;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
这是我的MainActivity
:
public class MainActivity extends AppCompatActivity {
private Intent intent;
private BroadcastReceiver mReceiver;
private EventListFragment eventListFragment;
private IntentFilter intentFilter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
private void setView() {
eventListFragment = (EventListFragment) getSupportFragmentManager().findFragmentById(R.id.frgEventList);
}
@Override
protected void onResume() {
intent = new Intent(this, EventService.class);
mReceiver = new MyReceiver(eventListFragment);
this.registerReceiver(mReceiver, intentFilter);
intent = new Intent(this, EventService.class);
startService(intent);
}
@Override
protected void onPause() {
super.onPause();
stopService(intent);
unregisterReceiver(mReceiver);
}
private static class MyReceiver extends BroadcastReceiver {
private WeakReference<EventListFragment> eventListFragment = null;
public MyReceiver(EventListFragment eventFragment) {
this.eventListFragment = new WeakReference<>(eventFragment);
}
@Override
public void onReceive(Context context, Intent intent) {
String mssg = intent.getStringExtra(KEY_MESSAGE);
EventListFragment eventFragment = eventListFragment.get();
if (mssg.equals(MESSAGE) && eventFragment != null) {
//Update recyclerView
eventFragment.eventToList();
}
}
}
}
这是我的EventListFragment
:
public class EventListFragment extends Fragment {
private View view;
private RecyclerView recyclerView;
private LinearLayoutManager mLayoutManager;
private EventAdapter eventAdapter;
private RequestData requestData;
private ArrayList<EventModel> eventList;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_event_list, container, false);
return view;
}
@Override
public void onResume() {
super.onResume();
setView();
setControl();
}
private void setView() {
recyclerView = (RecyclerView) view.findViewById(R.id.frg_recycler_view);
}
private void setControl() {
if (eventAdapter == null && mLayoutManager == null) {
eventList = new ArrayList<>();
eventAdapter = new EventAdapter(getActivity().getApplicationContext(), eventList);
mLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), LinearLayoutManager.VERTICAL));
recyclerView.setAdapter(eventAdapter);
}
recyclerView.addOnItemTouchListener(new RecyclerItemListener(getActivity().getApplicationContext(), recyclerView, new RecyclerItemListener.RecyclerTouchListener() {
@Override
public void onClickItem(View v, int position) {
EventModel model = eventList.get(position);
SQLiteHandler db = SQLiteHandler.getInstance(getActivity().getApplicationContext());
//some instances
}
@Override
public void onLongClickItem(View v, int position) {
}
}));
}
//make service call
public void eventToList() {
if (requestData == null) {
requestData = new RequestData(getActivity());
}
final ArrayList<EventModel> newList = new ArrayList<>(); //are you leaking?
requestData.getEventToday(new RequestData.VolleyCallback() {
@Override
public void onSuccess(JSONObject result) {
for (int i = 0; i < result.length(); i++) {
try {
JSONObject item = result.getJSONObject(Integer.toString(i));
EventModel eventModel = new EventModel();
String title = item.getString("title");
String start = item.getString("start");
String end = item.getString("end");
String date = item.getString("date");
eventModel.setDate(date);
eventModel.setStartTime(start);
eventModel.setEndTime(end);
eventModel.setTitle(title);
newList.add(eventModel);
} catch (JSONException e) {
e.printStackTrace();
}
}
eventAdapter.update(newList);
}
});
}
}
非常感谢!
答案 0 :(得分:1)
首先,一个设计考虑因素:是否有必要每10秒调用一次Web服务?您知道服务器数据何时/多久更改一次?
每次从Web服务器读取数据时,应用程序都需要做很多工作:创建多个对象,更新适配器等。此外,考虑网络流量,每隔10秒就使用一次网络。
你可以做些事情:
考虑到#2,我尝试重写eventToList方法:
public void eventToList() {
if (requestData == null) {
requestData = new RequestData(getActivity());
}
requestData.getEventToday(new RequestData.VolleyCallback() {
@Override
public void onSuccess(JSONObject result) {
ArrayList<EventModel> newList = new ArrayList<>();
JSONObject item;
EventModel eventModel;
String title;
String start;
String end;
String date;
for (int i = 0; i < result.length(); i++) {
try {
item = result.getJSONObject(Integer.toString(i));
eventModel = new EventModel();
title = item.getString("title");
start = item.getString("start");
end = item.getString("end");
date = item.getString("date");
eventModel.setDate(date);
eventModel.setStartTime(start);
eventModel.setEndTime(end);
eventModel.setTitle(title);
newList.add(eventModel);
} catch (JSONException e) {
e.printStackTrace();
}
}
eventAdapter.update(newList);
}
});
}