Android碎片内存泄漏 [英] Android Fragment Memory Leaks

查看:116
本文介绍了Android碎片内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在业余时间制作了一个小型应用程序,并且使用了很多片段.我对碎片还很陌生,但是我已经使用了许多资源来适当地使用....随着片段之间的变化,堆不断增长,导致内存泄漏.我以前使用活动"实现了我的应用程序,并且显着减少了内存泄漏.但是,现在我加入了碎片世界,就内存而言,我好像是从第一个平方开始的.

I'm making a small app in my sparetime and I'm using many fragments. I am fairly new to fragments however I have used many resources to use the appropriately... or so I thought. I am getting memory leaks as my heap continues to grow as I change from fragment to fragment. I had my app implemented with Activities previously and I had reduced the memory leaks significantly. However, now that I am joining the fragment world I feel as though I'm starting at square one when it comes to memory.

MainActivity.java

MainActivity.java

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);

    // Setting the content view of the Activity
    setContentView(R.layout.main);

    // Setting up the actionbar.
    ActionBar actionbar = getActionBar();
    actionbar.setSubtitle("");
    actionbar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME
            | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM);
    actionbar.setTitle("");
    actionbar = null;

    MainMenuFragment frag = new MainMenuFragment();

    getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, frag).commit();
}

此MainActivity还设置了ActionBar.

This MainActivity also sets up the ActionBar.

MainMenuFragment.java

MainMenuFragment.java

public class MainMenuFragment extends Fragment implements OnClickListener, LoaderCallbacks<Cursor> {

private static final String TAG = "MainMenuFragment";

SharedPreferences.Editor prefsEditor;
SharedPreferences prefs;

Bitmap[] picss = null;


static int width;

private static int FRIENDS = 0;
private static int PEOPLE = 1;
private static int MAP = 2;
private static int CAMERA = 3;
private static int TOP_TILE = 4;

LinearLayout topTile = null;
LinearLayout mainLayout;

private int NUM_OF_BUTTONS = 4;

ImageButton[] buttonList = null;

Bitmap background;

protected Activity activity;
protected String placeId = null;
protected ViewGroup container;
protected View view;

public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState); 
    activity = getActivity();

    view = getView();

    setupObjects(view);
    setupLayoutsAndImages(view);

    // Populate the UI by initiating the loader to retrieve the 
    // details of the venue from the underlying Place Content Provider.
    if (placeId != null)
      getLoaderManager().initLoader(0, null, this);
  }



public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.main_screen , container, false);
    this.container = container;

    return view;
}

public void onDestroyView() {
    super.onDestroyView();

    Log.d(TAG, "onDestroyView()");

    buttonList[FRIENDS].setImageBitmap(null);
    buttonList[PEOPLE].setImageBitmap(null);
    buttonList[MAP].setImageBitmap(null);
    buttonList[CAMERA].setImageBitmap(null);
    topTile.setBackground(null);

    // Removes all the onClickListeners
    buttonList[FRIENDS].setOnClickListener(null);
    buttonList[PEOPLE].setOnClickListener(null);
    buttonList[MAP].setOnClickListener(null);
    buttonList[CAMERA].setOnClickListener(null);
    topTile.setOnClickListener(null);

    // Sets buttonList and the topTile to null
     buttonList = null;
     topTile = null;

    // Recycles the bitmaps and sets picss to null
    if (picss != null) {
        picss[FRIENDS].recycle();
        picss[PEOPLE].recycle();
        picss[MAP].recycle();
        picss[CAMERA].recycle();
        picss = null;
    }

    mainLayout.setBackground(null);
    background.recycle();

    unbindDrawables(view);
    view = null;
    activity = null;
    System.gc();
}

private void unbindDrawables(View view) {
    if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
    }
    if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
        }
        ((ViewGroup) view).removeAllViews();
    }
}


public void onClick(View v) {
    Log.d(TAG, "Got within here.");
    switch (v.getId()) {
    case R.id.b_friendButton:

        FragmentTransaction trans = getActivity().getSupportFragmentManager().beginTransaction();
        trans.replace(R.id.fragment_container, new FriendsListFrag());
        trans.addToBackStack(null);
        trans.commit();
        break;
    case R.id.b_peopleButton:
        break;
    case R.id.b_mapButton:
        break;
    case R.id.b_CameraButton:
        break;
    case R.id.ll_Dynamic_Tile:
        break;
    }

}

private void setupObjects(View view) {

    Log.d(TAG, "Attempting to setupObjects.");

    mainLayout = (LinearLayout) view.findViewById(R.id.MainActivity_Main_Layout);
    topTile = (LinearLayout) view.findViewById(R.id.ll_Dynamic_Tile);

    buttonList = new ImageButton[NUM_OF_BUTTONS];
    buttonList[FRIENDS] = (ImageButton) view.findViewById(R.id.b_friendButton);
    buttonList[PEOPLE] = (ImageButton) view.findViewById(R.id.b_peopleButton);
    buttonList[MAP] = (ImageButton) view.findViewById(R.id.b_mapButton);
    buttonList[CAMERA] = (ImageButton) view.findViewById(R.id.b_CameraButton);

    picss = new Bitmap[5];

    buttonList[FRIENDS].setOnClickListener(this);
    buttonList[PEOPLE].setOnClickListener(this);
    buttonList[MAP].setOnClickListener(this);
    buttonList[CAMERA].setOnClickListener(this);

    int width = getActivity().getWindowManager().getDefaultDisplay().getWidth();
    int height = getActivity().getWindowManager().getDefaultDisplay().getHeight();

    background = GetImage.decodeSampledBitmapFromResource(getResources(),
            R.drawable.background2, width, height);

    System.out.println(mainLayout == null);

    mainLayout.setBackground(new BitmapDrawable(getResources(), background));

}

private void setupLayoutsAndImages(View view) {

    Log.d(TAG, "Attempting to setupLayoutsAndImages.");

    System.out.println("Width: " + width);
    final ImageButton myButton = (ImageButton) getView().findViewById(R.id.b_friendButton);
    getView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        public void onGlobalLayout() {
            System.out.println("Fragwidth: " + getView().getWidth());
            System.out.println("FragHeight: " + getView().getHeight());
            System.out.println("Button: " + myButton.getWidth());
            width = myButton.getWidth();

            System.out.println("Width: " + width);

            getView().getViewTreeObserver().removeGlobalOnLayoutListener(this);

            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                    width, width, 1.0f);
            int marg = (int) getResources().getDimension(
                    R.dimen.main_buttonpadding);
            params.setMargins(marg, marg, marg, marg);

            // Setting the params for the buttons.
            buttonList[FRIENDS].setLayoutParams(params);
            buttonList[PEOPLE].setLayoutParams(params);
            buttonList[MAP].setLayoutParams(params);
            buttonList[CAMERA].setLayoutParams(params);

            picss[FRIENDS] = GetImage.decodeSampledBitmapFromResource(
                    getResources(), R.drawable.tilefriendsmall, width, width);
            picss[PEOPLE] = GetImage.decodeSampledBitmapFromResource(
                    getResources(), R.drawable.tilepeoplesmall, width, width);
            picss[MAP] = GetImage.decodeSampledBitmapFromResource(
                    getResources(), R.drawable.tilemapsmall, width, width);
            picss[CAMERA] = GetImage.decodeSampledBitmapFromResource(
                    getResources(), R.drawable.tilecamerasmall, width, width);
            picss[TOP_TILE] = GetImage.decodeSampledBitmapFromResource(
                    getResources(), R.drawable.tilefriendlong, width, width);

            // Setting up the background for the buttons.
            buttonList[FRIENDS].setImageBitmap(picss[FRIENDS]);
            buttonList[FRIENDS].setAlpha(0.6f);
            buttonList[PEOPLE].setImageBitmap(picss[PEOPLE]);
            buttonList[PEOPLE].setAlpha(0.6f);
            buttonList[MAP].setImageBitmap(picss[MAP]);
            buttonList[MAP].setAlpha(0.6f);
            buttonList[CAMERA].setImageBitmap(picss[CAMERA]);
            buttonList[CAMERA].setAlpha(0.6f);

            LinearLayout.LayoutParams topParams = new LinearLayout.LayoutParams(
                    topTile.getWidth(), width);
            topParams.setMargins(marg, marg, marg, marg);
            topTile.setLayoutParams(topParams);
            topTile.setBackground(new BitmapDrawable(getResources(),
                    picss[TOP_TILE]));
            topTile.setAlpha(0.6f);
        }
    });

}

给出上面的代码,当我切换到FriendsListFrag()时,我保留为MainMenuFragment分配的先前的内存.我曾尝试使用Memory Analyzer,但运气不佳.

Given the code above, when I switch to the FriendsListFrag() I retain the previous memory that was allocated for the MainMenuFragment. I have tried to use the Memory Analyzer but have had little luck with it.

推荐答案

您将继续创建(并附加)片段的新实例.

You keep creating (and attaching) a new instance of your fragment.

更改此:

 MainMenuFragment frag = new MainMenuFragment();

 getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, frag).commit();

类似:

Fragment fragment = getSupportFragmentManager().
                   findFragmentById(R.id.fragment_container);
    if ( fragment == null ) {
        fragment = new MainMenuFragment();
            getSupportFragmentManager()
            .beginTransaction()
            .add(R.id.fragment_container, fragment, "SOME_TAG_IF_YOU_WANT_TO_REFERENCE_YOUR_FRAGMENT_LATER")
            .commit();
    } 

FragmentManager保留Fragments的引用并自行处理.您可以根据需要删除它们(在调用onSaveInstance()之前),方法是使用FragmentManager中的.detach()方法.

The FragmentManager keeps references of the Fragments and handles that by itself. You can remove them if you want (before calling the call to onSaveInstance()) by using .detach() method in the FragmentManager.

您可以这样做:

Fragment f = getSupportFragmentManager().findFragmentByTag("SOME_TAG_IF_YOU_WANT_TO_REFERENCE_YOUR_FRAGMENT_LATER");

if ( f != null ) {
   getSupportFragmentManager().detach(f);
}  

注意:这都是伪代码,我没有测试,可能有错别字,但您知道了

Note: This is all pseudo-code and I didn't test it, there might be typos, but you get the idea

这篇关于Android碎片内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆