簡體   English   中英

android GC到底如何工作?

[英]how android GC exactly works?

我知道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 );
 }

編輯:

這是我的代碼。 我使用MAT:最大對象:com.android.internal.policy.impl.PhoneWindow $ DecorView

通過使用MAT,我發現DecorView對象是問題,當我將屏幕旋轉7次導致OOM應用崩潰時,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);
    }
}

GC正在清理您的對象,並且(實際上)您無法執行任何操作,這是語言屬性(我認為這是個很棒的功能)。 您無需在“ onFinish”中執行任何操作,系統會為您清除內容,是的-如果您想在設備旋轉時保留一些數據(例如,您說“活動已被銷毀”並且所有引用),您可以使用onSaveInstanceState 有關根據GC HERE保存數據的更多信息

根據您的情況,您只想從以前的方向破壞以前的設置,對嗎?

最好的方法是android:configChanges =“ orientation | screenSize”

主題問題,請檢查此內容為什么調用System.gc()的做法不好?

在您的應用程序中調用system.gc時,您無法控制收集器在您的應用程序中殺死的內容,這可能會引起很多麻煩,例如nullpointers等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM