android - fragment 内存泄漏

标签 android android-fragments fragment android-memory

我的 Android 应用程序中有 4 个 fragment 。我有一个 FragmentPagerAdapter 来填充 ViewPager

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

问题是当我滑入 fragment 时,其他 fragment 正在被破坏(被垃圾收集器?)。我怎样才能避免这种情况?

fragment 适配器:

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

}

最佳答案

您可以使用setOffscreenPageLimit (int limit) ViewPager 的方法来增加内存中保存的 fragment 数量。

默认值为 1,表示内存中有 3 个 fragment 。 ( Activity 的 1 个左侧和 1 个右侧)。

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

关于android - fragment 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30963057/

相关文章:

android - 原始数组大小和 list.size 返回不同的值

android - Activity 中的 fragment 在 ListView 的 setAdapter 中获取上下文 null

Android - 使用 fragment 控制我的选项卡布局中每个选项卡的内容

android - fragment 过渡时屏幕闪烁

android - 使用手机的电视 Remote

android - 如何将 SetOnClickListener() 设置为 EditTextPreference 对话框的确定​​按钮?

android - 为什么以及何时应该使用 android Log 类?

android - 如何在选项卡中创建选项卡

javascript - 工具栏隐藏在 listView 中向上滚动但向下滚动时不会返回

Android & Robotium - 测试 fragment 是否出现?