Fragment Memory Leak

453 views Asked by At

I have 4 fragments in my android app. I have a FragmentPagerAdapter to fill the ViewPager.

Also I'm extending FragmentActivity in main activity.

The problem is when I slide in fragments, other fragments are destroying(by garbage collector?). How can I avoid this?

FragmentAdapter:

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 Fragments have a TextView. Other Fragment has a button and a progress bar:

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();
    }

}
1

There are 1 answers

1
LordRaydenMK On BEST ANSWER

You can use the setOffscreenPageLimit (int limit) method of the ViewPager to increase the number of fragments kept in memory.

The default is 1 meaning there are 3 fragments in memory. (1 left and 1 right of the active one).

You can try with 2 or 3. But don't go too high it might eat too much memory.