我知道GC会处理没有引用它的对象,但我不知道它是如何工作的。 在这个简单的android代码中我们有一个活动和textview,我知道当屏幕旋转整个活动被破坏和android创建一个新的。 GC可以摧毁以前的活动吗? 是不是因为textview持有一个参考活动,整个活动从GC中存活? 我是否需要在完成活动(或类似的东西)上做一些事情来发布参考?
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView textview = new TextView(this);
textview .setText("Leaks are bad");
setContentView(textview );
}
Edite:
这是我的代码。 MAT使用MAT: 最大的对象:com.android.internal.policy.impl.PhoneWindow $ DecorView通过使用MAT我发现DecorView对象是问题,当我用OOM旋转屏幕7次app崩溃时,MAT报告中确实有7个DecorView对象。
package atsoft.law.reader;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView;
import atsoft.law.R;
import atsoft.law.selecttext.NewHighlightDialog;
public class ReaderActivity extends BaseReaderActivity
{
Bundle bundle;
MainDialogFragment mainDialogFragment;
NewHighlightDialog newHighlightDialog;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
bundle = getIntent().getExtras();
setLawID(bundle.getInt("law_id", 0));
setCurrentPage(bundle.getInt("madde_id", 0));
mainDialogFragment = new MainDialogFragment();
adapter.setMainDialogFragment(mainDialogFragment);
requestLaw(lawID);
}
/////////////////OnLawReceived//////////////
@Override
protected void OnLawReceived()
{
adapter.PrePairAdapter(getSupportFragmentManager(),null, this, lawID);
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(getCurrentPage());
Log.i("total", String.valueOf(Runtime.getRuntime().totalMemory()));
Log.i("max", String.valueOf(Runtime.getRuntime().maxMemory()));
Log.i("free", String.valueOf(Runtime.getRuntime().freeMemory()));
}
@Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putInt("current_viewpager_page", viewPager.getCurrentItem());
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
super.onRestoreInstanceState(savedInstanceState);
if(savedInstanceState != null)
{
setCurrentPage(savedInstanceState.getInt("current_viewpager_page", 0));
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if(keyCode==KeyEvent.KEYCODE_MENU)
{
adapter.Prepair2();
mainDialogFragment.Initialize(this, viewPager, adapter);
mainDialogFragment.show(getSupportFragmentManager(),null);
return true;
}
else if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
{
viewPager.setCurrentItem(viewPager.getCurrentItem()+1);
return true;
}
else if(keyCode == KeyEvent.KEYCODE_VOLUME_UP)
{
viewPager.setCurrentItem(viewPager.getCurrentItem()-1);
return true;
}
else if(keyCode == KeyEvent.KEYCODE_BACK)
{
if(mainDialogFragment.isAdded())
{
mainDialogFragment.dismiss();
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.reader, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings)
{
return true;
}
return super.onOptionsItemSelected(item);
}
/////////ViewPager Page Events/////
@Override
public void onPageScrolled(int i, float v, int i2) {
}
@Override
public void onPageSelected(int i) {
if (newHighlightDialog != null) newHighlightDialog.dismissAndDeactivateTextSelector();
}
@Override
public void onPageScrollStateChanged(int i) {
}
public NewHighlightDialog getHighlightDialog()
{
if(this.newHighlightDialog == null) this.newHighlightDialog = new NewHighlightDialog(this);
return this.newHighlightDialog;
}
@Override
protected void onDestroy()
{
Log.i("BaseReaderActivity", "onDestroy ");
super.onDestroy();
unbindDrawables(findViewById(R.id.root_in_readeractivity_layout));
mainDialogFragment.releaseReference();
mainDialogFragment = null;
if(newHighlightDialog != null)
{
newHighlightDialog.realestReference();
newHighlightDialog = null;
}
getAdapter().releaseReference();
System.gc();
}
private void unbindDrawables(View view) {
if (view.getBackground() != null)
view.getBackground().setCallback(null);
if (view instanceof ImageView) {
ImageView imageView = (ImageView) view;
imageView.setImageBitmap(null);
} else if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++)
unbindDrawables(viewGroup.getChildAt(i));
if (!(view instanceof AdapterView))
viewGroup.removeAllViews();
}
}
}
public abstract class BaseReaderActivity extends ActionBarActivity implements OnThreadFinishListener, ViewPager.OnPageChangeListener
{
protected int lawID = 0;
protected int vpCurrentPage = 0;
protected FragmentAdapter adapter;
protected ViewPager viewPager;
private GlobalData globalData;
ProgressDialog progressDialog;
private void Init()
{
globalData= (GlobaData) this.getApplicationContext();
adapter = FragmentAdapter.getInstance(getSupportFragmentManager());
viewPager = (ViewPager) findViewById(R.id.vp);
viewPager.setOnPageChangeListener(this);
progressDialog = new ProgressDialog(this);
}
protected FragmentAdapter getAdapter()
{
return FragmentAdapter.getInstance(getSupportFragmentManager());
}
protected ViewPager getPager()
{
return this.viewPager;
}
protected GlobalStack getGlobalData()
{
return this.globalData;
}
protected DbCenter getDb()
{
return DbCenter.getInstance(this);
}
protected void setLawID(int id)
{
this.lawID = id;
}
protected int getLawID()
{
return this.lawID;
}
protected void setCurrentPage(int page)
{
this.vpCurrentPage = page;
}
protected int getCurrentPage()
{
return this.vpCurrentPage;
}
protected void requestLaw(int lawID)
{
if(!getGlobalData().checkLawAvailability(lawID))
{
this.UploadLawToGlobalData(lawID);
return;
}
else
{
this.OnLawReceived();
}
}
protected abstract void OnLawReceived();
protected void UploadLawToGlobalData(int lawID)
{
progressDialog.setText(LawIDs.getFaNameById(lawID));
progressDialog.show();
getDb().Prepair(lawID, this);
}
public Law getCurrentLaw()
{
return getGlobalData().getTheLaw();
}
@Override
public void threadFinished() throws IOException, XmlPullParserException
{
getGlobalData().UploadToGlobalData(getDb().getLaw());
this.OnLawReceived();
Log.i("BaseReaderActivity","upload completed !");
Log.i("BaseReaderActivity", "OnLawReceived");
progressDialog.hide();
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_main_);
Init();
getGlobalData().Init();
viewPager.setOffscreenPageLimit(2);
viewPager.setSoundEffectsEnabled(true);
adapter.setViewPager(viewPager);
}
}
答案 0 :(得分:0)
GC正在清理你的物品,并且(在实践中)你无法做任何事情,这是语言属性(在我看来很棒的功能)。你不必在&#34; onFinish&#34;中做任何事情,系统会为你清理东西,是的 - 所有你的对象,小部件等等,如果你想在设备旋转时保留一些数据(就像你一样)说活动被销毁,所有它的引用都可以使用onSaveInstanceState。有关针对GC保存数据的更多信息HERE
答案 1 :(得分:0)
根据您的情况,您只想破坏先前方向的先前设置,对吧?
最好的方法是 机器人:configChanges = “取向|屏幕尺寸”
主题问题,请查看此Why is it bad practice to call System.gc()?
在你的应用程序中调用system.gc,你无法控制收集器在你的应用程序中杀死什么,这可能会导致很多麻烦,比如nullpointers等。