Android:View如何绘制组件?

标签 android view handler

安卓问题: 当我将文本设置为 View 时, View 何时会更新 UI? 这是我的案例 1:

for(int i=0;i< 2000; i++){
    aTextView.setText("a"+i);
}

aTextView 是从 TextView 扩展而来的 MyTextView。我将 onDraw 改写为:

public static int counterP = 0;

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    counterP++;
    Log.d("MYButton", "onDraw: " + counterP);
}

从日志中可以看出,打印的counterP不是后继的。在循环中,onDraw方法只被调用了2-4次。

我又做了一个测试,案例2:

boolean notInit = true;
List<String> cmdList = null;
long stSelfRefresh = 0;
String contentStr;
TextView selfTv;

public void onSelfRefreshTv(View v) {
    if (cmdList == null || cmdList.isEmpty()) {
        Log.e(TAG, "empty now, reset");
        notInit = true;
    }
    if (notInit) {
        cmdList = new ArrayList<String>();
        for (int i = 0; i < 2000; i++) {
            cmdList.add("a" + i);
        }
        stSelfRefresh = SystemClock.uptimeMillis();
        notInit = false;
        selfTv = (MyTextView) findViewById(R.id.mytv);
    }
    contentStr = cmdList.remove(0);
    Log.d(TAG, "contentStr = " + contentStr);
    selfTv.setText(contentStr);

    if (!cmdList.isEmpty()) {
        if (!mHandler.sendEmptyMessage(99)) {
            Log.e(TAG, "SKIP my self");
        }
    } else {
        Log.d(TAG, "Cost time: " + (SystemClock.uptimeMillis() - stSelfRefresh));
    }
}

private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case 99:
                onSelfRefreshTv(null);
                break;
            default:
                break;
        }
    }
};

情况 2 的结果是 counterP 被打印出来。 1-2000。

不知道为什么每次都更新textView? 你有什么想法吗?

提前致谢。

******添加案例 3 ***********

for(int i=0;i< 2000;i++){ 
   contentStr = cmdList.remove(0);
   mHandler.sendEmptyMessage(100);

}  

private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case 100:
                selfTv.setText(contentStr);
                break;
            default:
                break;
        }
    }
};       

******案例 3 结束********** 案例3的测试结果与案例1类似。

最佳答案

看起来您正在 UI Thread 上运行您的代码。

这意味着:只要你的代码在运行,绘图代码就不能运行。 onDraw() 在循环完成计数后调用,并且只有最后一个值实际绘制在显示器上。
就这么简单。

如果你想在显示器上计数,你可以使用 AsyncTask 将计数部分移动到非 UI Thread:

    new AsyncTask<Void,Integer, Void>() {
        @Override
        protected Void doInBackground(Void... voids) {
            for (int i =0; i<2000; i++) {
                publishProgress(i);
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            aTextView.setText("a"+values[0]);
        }
    };

你的第二种情况是这样的:

  1. 您准备包含所有 2000 个元素的列表。
  2. 将列表的第一个元素设置为 TextView 并从列表中删除该项。
  3. 一旦系统认为合适,就向自己发送消息以在 UI Thread 上运行。
  4. 放开对 UI 线程的控制。
  5. 您的代码实际上已经完成,系统调用onDraw()
  6. 来自 4 的消息得到处理,您从 2 重新开始。

您会看到系统在循环中间控制了 UI Thread。这就是它明显计数的原因。

案例 3 不同于案例 2:

您正在循环发送 2000 条消息,而没有让系统处理它。

关于Android:View如何绘制组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18760679/

相关文章:

mysql - 在 MySQL 中创建 View 并将行转换为列

sql - 如何重写 SQL xpath 查询以创建索引 View

安卓延迟文本

java - 无法通过回调方法更新textview

java - 以下哪种 SQLite 数据库方法在存储使用和查找速度方面更高效?

asp.net-mvc - 如何在单击按钮时将部分 View 呈现为模态弹出窗口?

android - 如何在 android 中进行实时音频流时处理电话

android - Android:使用不同的资源集构建项目

android - 如何从Android上的方位角获取罗盘方向

python - 处理并重新引发 python 日志记录模块抛出的异常