2

LeakCanary 在我的 Android 应用程序中报告了内存泄漏。我已经谷歌搜索和研究了几天,找不到任何解决方案。泄露的对象是一个名为“MakeFire”的 Activity 实例。它似乎与android.view.WindowManagerGlobal有关。谁能指出泄漏是如何发生的,以及如何解决?

这是 LeakCanary ScreenCap

这是 MakeFire Activity 的源代码

public class MakeFire extends SharedMethod implements StatusBarFragment.OnFragmentInteractionListener,
    DayTimeFragment.OnFragmentInteractionListener, BackButtonFragment.OnFragmentInteractionListener {


private Button firePlough;
private Button bowDrill;
private TextView makeFireWithBowDrillTime;
private TextView requirementTextview;
private Button performButton;

private String selectedButton;

private boolean firePloughOn;
private boolean bowDrillOn;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_make_fire);

    firePlough = (Button) findViewById(R.id.firePlough);
    bowDrill = (Button) findViewById(R.id.bowDrill);
    makeFireWithBowDrillTime = (TextView) findViewById(R.id.makeFireWithBowDrillTime);
    requirementTextview = (TextView) findViewById(R.id.requirementTextview);
    performButton = (Button) findViewById(R.id.performButton);
}

@Override
public void onDestroy() {
    super.onDestroy();
    RefWatcher refWatcher = MyApplication.getRefWatcher(this);
    refWatcher.watch(this);
}
@Override
public void onBackPressed() {
    Bundle extra = new Bundle();
    extra.putString("classToGoBack", getClass().getName());
    Intent intent = new Intent(this, InGameMenu.class);
    intent.putExtras(extra);
    startActivity(intent);
}
@Override
public void onResume() {
    super.onResume();
    GameData.useImmersiveModeSticky(this);
}

@Override
public void onStop() {
    super.onStop();
    try {
        //save on the latest save file
        FileOutputStream latestSavedGame = openFileOutput("latestSavedGame", Context.MODE_PRIVATE);
        ObjectOutputStream latestGameData = new ObjectOutputStream(latestSavedGame);
        latestGameData.writeObject(GameData.GDI);
        latestSavedGame.close();
    } catch (Exception e) {
        //TODO - delete it before uploading the app
        GameData.GDI.showPlainMsg("sharedMethodProblem!", this);
        final StringWriter sw = new StringWriter();
        final PrintWriter pw = new PrintWriter(sw, true);
        e.printStackTrace(pw);
        GameData.GDI.showPlainMsg(sw.getBuffer().toString(), this);
    }
    boolean savedGameIsFine;
    try {
        FileInputStream latestSavedGame = openFileInput("latestSavedGame");
        ObjectInputStream latestGameData = new ObjectInputStream(latestSavedGame);
        savedGameIsFine = (latestGameData.readObject() != null);
        latestSavedGame.close();
    } catch (Exception e) {
        savedGameIsFine = false;
    }
    if (savedGameIsFine) {
        try {
            //save on the latest save file
            FileOutputStream latestSavedGame = openFileOutput("latestSavedGameBackup", Context.MODE_PRIVATE);
            ObjectOutputStream latestGameData = new ObjectOutputStream(latestSavedGame);
            latestGameData.writeObject(GameData.GDI);
            latestSavedGame.close();
        } catch (Exception e) {
        }
    } else {

    }
}
@Override
protected void onStart() {
    super.onStart();
    updateAllViews();
    requirementTextview.setVisibility(View.INVISIBLE);
    performButton.setVisibility(View.INVISIBLE);
}
//method for updating all amendable views in the page
private void updateAllViews() {
    //visibility of fire plough button
    if (GameData.GDI.anyThisInventoryAvailable(GameData.FIRE_PLOUGH) &&
            GameData.GDI.anyThisInventoryAvailable(GameData.TINDER) &&
            (!GameData.GDI.stormOn || GameData.GDI.currentLocation.campfireWindBlock)
            ) {
        firePlough.setCompoundDrawablesWithIntrinsicBounds(0,R.drawable.ic_fireplow_3_f,0,0);
        firePlough.setTextColor(ContextCompat.getColor(this, R.color.buttonOnColour));
        firePloughOn = true;
    }
    else {
        firePlough.setCompoundDrawablesWithIntrinsicBounds(0,R.drawable.ic_fireplow_3_f_o,0,0);
        firePlough.setTextColor(ContextCompat.getColor(this, R.color.buttonOffColour));
        firePloughOn = false;
    }
    //visibility of bow drill button
    if (GameData.GDI.bowDrillUnlocked) {
        bowDrill.setVisibility(View.VISIBLE);
        makeFireWithBowDrillTime.setVisibility(View.VISIBLE);
        if (GameData.GDI.anyThisInventoryAvailable(GameData.BOW_DRILL) &&
                GameData.GDI.anyThisInventoryAvailable(GameData.TINDER) &&
                (!GameData.GDI.stormOn || GameData.GDI.currentLocation.campfireWindBlock)
                ) {
            bowDrill.setCompoundDrawablesWithIntrinsicBounds(0,R.drawable.ic_bow_drill_3_f,0,0);
            bowDrill.setTextColor(ContextCompat.getColor(this, R.color.buttonOnColour));
            bowDrillOn = true;
        }
        else {
            bowDrill.setCompoundDrawablesWithIntrinsicBounds(0,R.drawable.ic_bow_drill_3_f_o,0,0);
            bowDrill.setTextColor(ContextCompat.getColor(this, R.color.buttonOffColour));
            bowDrillOn = false;
        }
    }
    updateStatusBarFragment();
    updateDayTimeFragment();
}

public void makeFireWithFirePlough(View view) {
    if (firePloughOn) {
        performButton.setVisibility(View.VISIBLE);
    }
    else {
        performButton.setVisibility(View.INVISIBLE);
    }
    requirementTextview.setVisibility(View.VISIBLE);
    requirementTextview.setText(R.string.makeFireWithFirePloughRqm);
    selectedButton = "fire plough";
}
public void makeFireWithBowDrill(View view) {
    if (bowDrillOn) {
        performButton.setVisibility(View.VISIBLE);
    }
    else {
        performButton.setVisibility(View.INVISIBLE);
    }
    requirementTextview.setVisibility(View.VISIBLE);
    requirementTextview.setText(R.string.makeFireWithBowDrillRqm);
    selectedButton = "bow drill";
}
public void perform(View view){
    if (!GameData.GDI.stormOn || GameData.GDI.currentLocation.campfireWindBlock){
        switch (selectedButton){
            case "fire plough":
                String msgToShow = "";
                String extraInfo = "";
                String[] timePassMsg;
                Bundle extras = new Bundle();
                //timepass method must run before the fireToLast method
                timePassMsg = GameData.GDI.timePass(30, 1, 1, 1, this);
                if (GameData.GDI.anyThisInventoryInBackpack(GameData.TINDER)) {
                    GameData.GDI.setInventoryAmount(GameData.TINDER, true, -1);
                }
                else {
                    GameData.GDI.setInventoryAmount(GameData.TINDER, false, -1);
                }
                extras.putString("toolUsed", getString(R.string.usedTinderMsg));
                //update tool durability
                GameData.GDI.firePloughDurability = GameData.GDI.updateInventoryDurability(GameData.FIRE_PLOUGH, GameData.GDI.firePloughDurability, GameData.FIRE_PLOUGH_MAX_DURABILITY);
                //Because in GameCamp.updateInventoryDurability, if the tool broke, it will reset the durability to its maxDurability;
                //so if these 2 numbers equal, the tool just broke
                if (GameData.GDI.firePloughDurability == GameData.FIRE_PLOUGH_MAX_DURABILITY) {
                    extraInfo += getString(R.string.firePloughBreakMsg) + "\n\n";
                }
                GameData.GDI.bowDrillUnlockCounter += 1;
                if (Math.random() < 0.75) {
                    GameData.GDI.currentLocation.fireOn = true;
                    GameData.GDI.currentLocation.fireToLast += 10;
                    msgToShow += getString(R.string.success) + "\n";
                    extras.putString("className", "Fire");
                }
                else {
                    msgToShow += getString(R.string.fail) + "\n";
                    if (!GameData.GDI.bowDrillUnlocked) {
                        if (GameData.GDI.bowDrillUnlockCounter >= 3) {
                            extraInfo += getString(R.string.bowDrillUnlockMsg) + "\n\n";
                            GameData.GDI.bowDrillUnlocked = true;
                            GameData.GDI.setCraftingAlertIcon(3);
                        }
                    }
                    extras.putString("className", "Make Fire");
                }
                Intent intent = new Intent(this, LoadingPage.class);
                extras.putString("actionName", getString(R.string.makingFireWithFirePlough));
                extras.putInt("timeNeeded", 30);
                extras.putString("msgToShow", msgToShow);
                extras.putString("extraInfo", extraInfo);
                extras.putString("timePassMsg", timePassMsg[0]);
                extras.putString("deathReason", timePassMsg[1]);
                intent.putExtras(extras);
                startActivity(intent);
                break;
            case "bow drill":
                String msgToShow1 = "";
                String extraInfo1 = "";
                String[] timePassMsg1;
                Bundle extras1 = new Bundle();
                //timepass method must run before the fireToLast method
                timePassMsg1 = GameData.GDI.timePass(10, 1, 1, 1, this);
                if (GameData.GDI.anyThisInventoryInBackpack(GameData.TINDER)) {
                    GameData.GDI.setInventoryAmount(GameData.TINDER, true, -1);
                }
                else {
                    GameData.GDI.setInventoryAmount(GameData.TINDER, false, -1);
                }
                extras1.putString("toolUsed", getString(R.string.usedTinderMsg));
                //update tool durability
                GameData.GDI.bowDrillDurability = GameData.GDI.updateInventoryDurability(GameData.BOW_DRILL, GameData.GDI.bowDrillDurability, GameData.BOW_DRILL_MAX_DURABILITY);
                //Because in GameCamp.updateInventoryDurability, if the tool broke, it will reset the durability to its maxDurability;
                //so if these 2 numbers equal, the tool just broke
                if (GameData.GDI.bowDrillDurability == GameData.BOW_DRILL_MAX_DURABILITY) {
                    extraInfo1 += getString(R.string.bowDrillBreakMsg) + "\n\n";
                }
                if (Math.random() < 0.95) {
                    GameData.GDI.currentLocation.fireOn = true;
                    GameData.GDI.currentLocation.fireToLast += 10;
                    msgToShow1 += getString(R.string.success) + "\n";
                    extras1.putString("className", "Fire");
                }
                else {
                    msgToShow1 += getString(R.string.fail) + "\n";
                    extras1.putString("className", "Make Fire");
                }
                Intent intent1 = new Intent(this, LoadingPage.class);
                extras1.putString("actionName", getString(R.string.makingFireWithBowDrill));
                extras1.putString("className", "Fire");
                extras1.putInt("timeNeeded", 10);
                extras1.putString("msgToShow", msgToShow1);
                extras1.putString("extraInfo", extraInfo1);
                extras1.putString("timePassMsg", timePassMsg1[0]);
                extras1.putString("deathReason", timePassMsg1[1]);
                intent1.putExtras(extras1);
                startActivity(intent1);
                break;
        }
    }
    else {
        GameData.GDI.showPlainMsg(getString(R.string.cannotMakeFireInStormMsg), this);
    }
}
//fragment method
public void updateStatusBarFragment() {
    StatusBarFragment statusBarFragment = (StatusBarFragment)getSupportFragmentManager().findFragmentById(R.id.statusBarFragment);
    statusBarFragment.updateStatusBar();
}
public void updateDayTimeFragment() {
    DayTimeFragment dayTimeFragment = (DayTimeFragment)getSupportFragmentManager().findFragmentById(R.id.dayTimeFragment);
    dayTimeFragment.updateDayTimeView();
}
public void backButton(View view){
    Intent intent = new Intent(this, Fire.class);
    startActivity(intent);
}

}

4

0 回答 0