简体   繁体   中英

Android: How the View draw the component?

Android question: When I set text to a view, when the view will update the UI? Here is my case 1:

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

aTextView is a MyTextView, that extends from TextView. I overwirte the onDraw as:

public static int counterP = 0;

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

From the log, I can see, the printed counterP is not consequent. In the loop, the onDraw method is called only 2-4 times.

I did another test, case 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;
        }
    }
};

The result of case 2 is the counterP is printed out consequent. 1-2000.

I don't know why the textView is updated for each time? Do you have any idea for this?

Thanks in advance.

** * *** add case 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;
        }
    }
};       

** * *** end of case 3 * ** * ** * *** The test result for case 3 is similar with case 1.

It looks like you are running your code on the UI Thread .

This means: as long as your code is running, the drawing code can not run. The onDraw() is called after your loop finished counting and only the last value is actually drawn on the display.
It's as simple as that.

If you want something count up on your display, you can use a AsyncTask to move the counting part into a non-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]);
        }
    };

Your second case is like this:

  1. You prepare the list with all 2000 elements.
  2. Set the first element of the list to the TextView and remove the item from the list.
  3. Send yourself a message to run on the UI Thread as soon as the system thinks it is appropriate.
  4. Let go the control of the UI Thread.
  5. Your code is actually finished and the system calls onDraw() .
  6. The message from 4 gets processed and you start again with 2.

You see that the system gets control over the UI Thread in the middle of your loop. That's why it's counting visibly.

Case 3 is different from 2:

You are sending 2000 messages in on loop without letting the system handle it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM