簡體   English   中英

如何從Web服務定期更新recyclerView而不會泄漏內存

[英]How to update recyclerView from web service periodically without leaking memory

我的應用程序使用Volley進行Web服務調用,以便每10秒更新一次recyclerView。 此外,內存使用量會在10秒內不斷增加,直到達到最大堆大小為止。 然后,GC開始執行其工作,但是內存使用率並沒有像開始時那樣下降。 使用Eclipse MAT或Android Studio分析器任務,我在代碼中找不到單個泄漏。

我想知道我的代碼中是否有泄漏的嫌疑人。 任何幫助將不勝感激。

以下我有3個班級:

  • EventService每10秒鍾使用sendBroadcast()MainActivity發送一條消息。

  • MainActiviy將使用BroadcastReceiverEventService獲取消息,並在其Fragment調用update操作

  • 位於MainActivity內部的EventListFragment包含一個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);

            }
        });

    }
}

非常感謝!

首先是設計上的考慮:是否有必要每10秒調用一次Web服務? 您知道服務器數據何時/多久更改一次嗎?

每次從Web服務器讀取數據時,應用程序都必須做很多工作:創建許多對象,更新適配器等。此外,考慮網絡流量,您每10秒鍾使用一次網絡。

您可以執行以下操作:

  1. 增加等待時間:這樣,您減少了創建對象的數量/每秒。
  2. 減少對臨時對象的本地引用(請參見以下代碼)
  3. 在添加新值之前,請檢查回收者視圖的適配器是否正確推遲了舊值。
  4. 評估是否可以使用技術推送數據,以避免數據輪詢。 您可以看到GCM

考慮因素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);
    }
 });

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM