片段内存泄漏

Fragment Memory Leak

我的 android 应用程序中有 4 个片段。我有一个 FragmentPagerAdapter 来填充 ViewPager.

此外,我还在主 activity 中扩展 FragmentActivity。

问题 是当我在碎片中滑动时,其他碎片正在破坏(通过垃圾收集器?)。我怎样才能避免这种情况?

片段适配器:

package com.quiz.Adapter;

public class FragmentAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments = new ArrayList<>();
    private Context ctx;

    public FragmentAdapter(FragmentManager fm, Context ctx) {
        super(fm);
        this.ctx = ctx;
        fragments.add(new FragmentMenu()); //same
        fragments.add(new FragmentMain());
        fragments.add(new FragmentMenu()); //same
        fragments.add(new FragmentMenu()); //same
    }

    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }


}

3 个片段有一个 TextView。其他Fragment有一个按钮和一个进度条:

package com.quiz.Activity.Fragments;


public class FragmentMain extends Fragment implements View.OnClickListener  {

    Timer timer;
    int gameStartIn = 0, ONE = 1, INTERVAL = 1000;
    Context context;
    boolean joinedToMulti = false;
    NormalButton multiGameButton;
    NextGameCounter nextGameCounter; //progressbar
    Store store;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_main, container, false);

        context = this.getActivity().getApplicationContext();
        store = new Store(context);
        multiGameButton = (NormalButton)view.findViewById(R.id.multiGameButton);
        multiGameButton.setOnClickListener(this);
        nextGameCounter = (NextGameCounter)view.findViewById(R.id.nextGameCounter);

        init();

        Toast("onCreateView");


        return view;
    }

    void Toast(String e){
        Toast.makeText(context, "_"+e, Toast.LENGTH_SHORT).show();
    }

    private void init() {

        getNextRoundDate();

        timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {

            @Override
            public void run() {

                gameStartIn--;

                if(gameStartIn < ONE) {
                    gameStartIn = 1;
                    timer = new Timer();
                    getNextRoundDate();
                } else {
                    //update ui
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            nextGameCounter.setProgress(gameStartIn);
                        }
                    });
                }

            }
        }, 0, INTERVAL);
    }

    private void getNextRoundDate() {
        new AsyncTask<Void, Void, ResponseModel>() {
            @Override
            protected ResponseModel doInBackground(Void... voids) {
                ResponseModel responseModel = ApiManager.getService().GameGetNextRoundDate();
                return responseModel;
            }

            @Override
            protected void onPostExecute(ResponseModel  e){
                gameStartIn = Integer.valueOf(e.getInfo()); //seconds
            }
        }.execute();
    }

    @Override
    public void onClick(View view) {

        if(view.getId() == R.id.multiGameButton){
            if(joinedToMulti)
                return;

            joinedToMulti = true;
            requestNewGame();
        }
    }

    @Override
    public void onPause(){
        super.onPause();
        stopGame();
    }

    @Override
    public void onResume(){
        super.onResume();
        multiGameButton.setText(getResources().getString(R.string.main_multiplayer_button_text));
    }

    private void stopGame() {
        if(joinedToMulti)
            sendLeaveLobbyRequest();
    }

    void sendLeaveLobbyRequest(){
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... voids) {
                ApiManager.getService().GameMatchLeaveRequest(new GameMultiRequestModel(store.getUid()));
                return null;
            }
        }.execute();
    }

    void requestNewGame(){
        new AsyncTask<Void, Void, ResponseModel>() {

            @Override
            protected ResponseModel doInBackground(Void... voids) {

                return ApiManager.getService().GameMatchRequest(new GameMultiRequestModel(store.getUid()));
            }

            @Override
            protected void onPostExecute(ResponseModel matchResponseModel){
                multiGameButton.setText(getString(R.string.main_multiplayer_joined_button_text));
                Toast.makeText(context, "Game starting in "+gameStartIn+" seconds.", Toast.LENGTH_LONG).show();
            }

        }.execute();
    }

}

您可以使用ViewPagersetOffscreenPageLimit (int limit)方法来增加内存中保存的片段数。

默认为1表示内存中有3个片段。 (活动的左1右1)。

您可以尝试使用 2 或 3。但不要设置得太高,否则可能会占用太多内存。