天文台在列表视图获取有时泄露 [英] chronometer in list view gets leaked sometimes

查看:139
本文介绍了天文台在列表视图获取有时泄露的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个天文台在我的列表视图。问题是,有时它被也就是说泄露我可以看到 OnChronometerTickListener 执行每一秒我已经浏览到另一个选项卡即使在或滚动列表视图项拿出来看,甚至pressed的首页按钮。这似乎对资源的浪费,因为我需要它来运行,只有当它实际上是可见的。

I have a chronometer in my list view. The problem is that sometimes it gets leaked i.e. i can see the OnChronometerTickListener executing every second even after i have navigated to another tab or scrolled the list view item out of view or even pressed the Home button. It seems a waste of resources, since i need it to run only when it is actually visible.

有没有办法避免这种行为呢?需要注意的是它发生只是有时。

Is there a way to avoid this behaviour? Note that it happens only sometimes.

public class TimerLayout extends LinearLayout {

    private static final String LOG_TAG = "TimerLayout";
    Button btn_endTimer;
    Button btn_cancelTimer;
    Chronometer cmt_timer;
    Runnable updateTimerThread;
    Handler handler;

    public TimerLayout(Context context, AttributeSet attrs) {
        super(context,attrs);

        setOrientation(LinearLayout.VERTICAL);

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.timer, this, true);
        cmt_timer = (Chronometer) getChildAt(0);
        btn_endTimer = (Button) ((ViewGroup) getChildAt(1)).getChildAt(0);
        btn_cancelTimer = (Button) ((ViewGroup) getChildAt(1)).getChildAt(1);

        btn_endTimer.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View view){
                cmt_timer.stop();
            }
        });

        btn_cancelTimer.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View view){
                cmt_timer.stop();
            }
        });

        cmt_timer.setOnChronometerTickListener(new OnChronometerTickListener() {

            @Override
            public void onChronometerTick(Chronometer arg0) {
                if(BuildConfig.DEBUG){Log.d(LOG_TAG,"onChronometerTick.objectid=" + System.identityHashCode(TimerLayout.this));}

            }
        });

    }

    public void init(Date startTime){
        cmt_timer.stop();
        if(startTime!=null){
            Date now = new Date();
            long elapsedTime = now.getTime() - startTime.getTime();
            cmt_timer.setBase(SystemClock.elapsedRealtime() - elapsedTime);
            cmt_timer.start();
        }

    }

}

我称之为的init 这个类中的 bindView()我的 cursorAdaptor 来启动它。

I call the init method of this class in the bindView() method of my cursorAdaptor to start it.

推荐答案

关键是要停止计时器在的onPause()片段/活性。

The trick is to stop the chronometers in the onPause() of the fragment/activity.

所以,我创建一个类来保存计时器:

So i create a class to hold the chronometers :

public class ChronometerHolder {
    private WeakHashMap<Date, Chronometer> chronometerMap;
    private static final String LOG_TAG = "ChronometerHolder";

    public ChronometerHolder() {
        chronometerMap = new WeakHashMap<Date, Chronometer>();
    }

    public void add(Date dt_startTime, Chronometer chronometer){
        chronometerMap.put(dt_startTime, chronometer);
    }

    public void remove(Date dt_startTime){
        chronometerMap.remove(dt_startTime);
    }

    public int getCount(){
        return chronometerMap.size();
    }

    public void startAll() {
        // start any chronometers that were paused
        if (chronometerMap.size() > 0) {
            Set<Entry<Date, Chronometer>> set = chronometerMap.entrySet();
            Iterator<Entry<Date, Chronometer>> iterator = set.iterator();
            Entry<Date, Chronometer> entry;
            while (iterator.hasNext()) {
                entry = (Entry<Date, Chronometer>) iterator.next();
                entry.getValue().start();
                }
            }
        }
    }

    public void stopAll() {
        // stop any chronometers that might be running
        if (chronometerMap.size() > 0) {
            Set<Entry<Date, Chronometer>> set = chronometerMap.entrySet();
            Iterator<Entry<Date, Chronometer>> iterator = set.iterator();
            Entry<Date, Chronometer> entry;
            while (iterator.hasNext()) {
                entry = (Entry<Date, Chronometer>) iterator.next();
                entry.getValue().stop();
                }
            }
        }
    }

然后我做出以下变化:

Then i make the below changes :


  1. 返回从的天文台表对象的init()

public Chronometer init(Date startTime){
    Chronometer obj = null;
    cmt_timer.stop();
    if(startTime!=null){
        Date now = new Date();
        long elapsedTime = now.getTime() - startTime.getTime();
        cmt_timer.setBase(SystemClock.elapsedRealtime() - elapsedTime);
        cmt_timer.start();
        obj = cmt_timer;
    }

    return obj;

}


  • 在片段,实例化holder类:

  • In the fragment, instantiate the holder class :

    ChronometerHolder chronometerHolder = new ChronometerHolder();
    


  • 每次初始化chrononmeter时间(在 bindView()的CursorAdapter ),加它的持有人:

  • Every time you initialize the chrononmeter( in the bindView() of the CursorAdapter), add it to the holder :

    Chronometer tmpChronometer = viewHolder.myTimer.init(dt_hitSessionStartTime);
    if(tmpChronometer != null){
        chronometerHolder.add(dt_hitSessionStartTime, tmpChronometer);
    }
    


  • 的onPause(),停止所有的计时器:

  • In onPause(), stop all the chronometers :

    chronometerHolder.stopAll();
    


  • onResume(),启动所有的计时器:

  • In onResume(), start all the chronometers :

    chronometerHolder.startAll();
    


  • 当您在preSS的Home键退出,而不是应用程序,然后重新打开应用程序时, bindView()呼叫不执行。这意味着计时器处于停止状态。因此,它在 onResume()来启动,因为在完成#5。

    When the you press the Home button instead of exiting the app, and then open the app again, the bindView() calls are not executed. That means the chronometers are in a stopped state. So it has to be started in onResume() as done in #5.

    这篇关于天文台在列表视图获取有时泄露的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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