Android:具有处理程序和runnable的ListView中的多个计时器. 2个问题

Android:具有处理程序和runnable的ListView中的多个计时器. 2个问题,第1张

概述我正在创建一个包含带有2列的ListView的应用程序.在第一列上应显示倒计时,在第二列上显示一个附加文本,用于说明倒计时的内容.下面你看到我的代码有效……或多或少.我有一个包含多行的列表视图,计时器正在滴答作响.一个问题是:我的runnable中的set.Text()似乎覆盖了所有行.例如.第1

我正在创建一个包含带有2列的ListVIEw的应用程序.在第一列上应显示倒计时,在第二列上显示一个附加文本,用于说明倒计时的内容.
下面你看到我的代码有效……或多或少.
我有一个包含多行的列表视图,计时器正在滴答作响.
一个问题是:
我的runnable中的set.Text()似乎覆盖了所有行.例如.第1行的runnable也设置为第2行和第3行,第2行的runnable也设置为1和3的文本,依此类推.这会导致第一列闪烁(具有正确的值和其他行的值).
如何为列表视图中的特定行设置文本?

下一个问题:
即使我从处理程序中删除回调,runnable也会继续运行.但是当活动处于后台或关闭时,不需要计时器滴答,我不想浪费系统资源.

我的活动:

public class TimerActivity extends ListActivity {MyTimerAdapter myTimerAdapter = null;ArrayList<Long> timerList = new ArrayList<Long>();ArrayList<String> textList = new ArrayList<String>();@OverrIDepublic voID onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentVIEw(R.layout.Listactivity);    myTimerAdapter = new MyTimerAdapter(this, R.layout.row, R.ID.tv_timer, R.ID.tv_text);    setlistadapter(myTimerAdapter);}@OverrIDeprotected voID onResume() {    super.onResume();    refreshVIEw();}@OverrIDeprotected voID onPause() {    myTimerAdapter.clear();    myTimerAdapter.notifyDataSetChanged();    super.onPause();}private voID refreshVIEw() {    myTimerAdapter.clear();    timerList.clear();    textList.clear();    // some code to read database and fill     // array timerList with a long value (used for displaying a countdown)     // and textList with some additional text    myTimerAdapter.add(timerList, textList);    myTimerAdapter.notifyDataSetChanged();}}

我的适配器:

public class MyTimerAdapter extends ArrayAdapter<String> {private Activity mContext;private ArrayList<Long> mTimer;private ArrayList<String> mText;private int mVIEwID;private int mVIEwIDFIEldTimer;private int mVIEwIDFIEldText;private int ListSize;private ArrayList<Handler> handlerList = new ArrayList<Handler>();private ArrayList<TimerRunnable> runList = new ArrayList<TimerRunnable>();public MyTimerAdapter(Activity context, int textVIEwResID, int tv1, int tv2) {    super(context, textVIEwResID);    mContext = context;    mVIEwID = textVIEwResID;    mVIEwIDFIEldTimer = tv1;    mVIEwIDFIEldText = tv2;    ListSize = 0;}public voID add(ArrayList<Long> timer, ArrayList<String> text) {    mTimer = timer;    mText = text;    ListSize = mText.size();    handlerList.clear();    runList.clear();}@OverrIDepublic voID clear() {    super.clear();    int i;    for (i=0; i<ListSize; i++) {        handlerList.get(i).removeCallbacksAndMessages(runList.get(i));        runList.get(i).stopHandler();    }}@OverrIDepublic int getCount() {    return ListSize;}@OverrIDepublic VIEw getVIEw(int position, VIEw convertVIEw, VIEwGroup parent) {    VIEw v = convertVIEw;    if (v == null) {        LayoutInflater vi = mContext.getLayoutInflater();        v = vi.inflate(mVIEwID, null);    }    long timerline = mTimer.get(position);    if (timerline != 0) {        TextVIEw tvTimer = (TextVIEw) v.findVIEwByID(mVIEwIDFIEldTimer);        if (tvTimer != null) {            tvTimer.setTag(position);            final Handler mTimerHandler = new Handler();            TimerRunnable timerTask = new TimerRunnable(tvTimer, tvTimer.getTag().toString(), timerline);            mTimerHandler.post(timerTask);            // save in array to stop later            handlerList.add(mTimerHandler);            runList.add(timerTask);        }    }    String textline = mText.get(position);    if (textline != null) {        TextVIEw tvText = (TextVIEw) v.findVIEwByID(mVIEwIDFIEldText);        if (tvText != null) {            tvText.setText(textline);        }    }    return v;}}

我的Runnable:

public class TimerRunnable implements Runnable {private TextVIEw tv;final Handler mTimerHandler = new Handler();String tag;long endtime;long sec;public TimerRunnable (TextVIEw tv, String tag, long endtime) {    this.tv = tv;    this.tag = tag;    this.endtime = endtime;}public voID run() {    if (tv.getTag().toString().equals(tag)) {        Calendar cal = Calendar.getInstance();        sec = endtime - (cal.getTimeInMillis() / 1000); //endtime - aktuelle Zeit        if (sec >= 0) {            // some code formatting the time in seconds to something like hh:mm:ss (var String txt)            tv.setText(txt);            System.out.println(txt);  // only for tests; so I Could see that runnable is still running            mTimerHandler.postDelayed(this, 1000);        }     }}public voID stopHandler() {    mTimerHandler.removeCallbacksAndMessages(null);}}

解决方法:

我会这样做:

>使用计时器
(http://developer.android.com/reference/java/util/Timer.html)和
让它每秒钟或其他任何时候定期运行.
>在ActivitIEs onCreate()中创建Timer对象,并在ActivitIEs onDestroy()中取消()更新计时器(或者更好地在onResume中启动它并在onPause()中取消它).这就是如何避免内存泄漏的最简单方法,即使活动已关闭,您的计时器也在运行.
>从正在运行的计时器更新ListVIEw.有两种选择:

>只需从计时器调用adapter.notifyDatasetChanged()即可.但这可能会导致“闪烁”的列表视图.但是,您可以尝试检查这是否可以在您的应用程序中工作,因为这是最简单的实现.
>直接更新ListVIEw中当前可见的TextVIEw

private voID updateTime(){int firstVisibleItemIndex = ListVIEw.getFirstVisibleposition();for (int i = 0; i < ListVIEw.getChildCount(); i++) {    VIEw v = ListVIEw.getChildAt(i);        YourItem item = (YourItem)adapter                .getItem(firstVisibleItemIndex + i));        VIEwHolder vh = (VIEwHolder) v.getTag();                            // Calculate the time somehow, i.e. call a methot on your data item                            vh.tvTimer.setText(item.getelapsedtime());    }}

}

所以我猜第二种选择是最好的.您可能想知道VIEwHolder是什么. VIEwHolder是一种提高ListVIEw性能的模式. http://developer.android.com/training/improving-layouts/smooth-scrolling.html#ViewHolder
适配器的问题是,每次用户滚动时都会调用findVIEwByID(). findVIEwByID()是一种昂贵的方法调用,因为它必须遍历所有视图子节点以找到具有给定ID的节点.在您的简单适配器中,它可能不会产生太大影响(因为您只有一个子视图,TextVIEw).但VIEwHolder是您应该在Adapter实现中始终使用的东西

总结

以上是内存溢出为你收集整理的Android:具有处理程序和runnable的ListView中的多个计时器. 2个问题全部内容,希望文章能够帮你解决Android:具有处理程序和runnable的ListView中的多个计时器. 2个问题所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1110320.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存