乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Android更新UI的幾種方法

       黃三歲大愛人生 2019-05-07

      第一種場景:

      在UI線程中更新UI,這種是最簡單的,直接更新UI即可。
      代碼如下

      public class MainActivity extends AppCompatActivity { private Button bt_click_me; private TextView tv_text; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt_click_me = findViewById(R.id.bt_click_me); tv_text = findViewById(R.id.tv_text); bt_click_me.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { tv_text.setText('111111111111111'); } }); } }

      第二種場景:

      從子線程中更新UI

      代碼如下

      public class MainActivity extends AppCompatActivity {
      
          private Button bt_click_me;
          private TextView tv_text;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              bt_click_me = findViewById(R.id.bt_click_me);
              tv_text = findViewById(R.id.tv_text);
      
              bt_click_me.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
      
                      Thread thread = new Thread(new Runnable() {
                          @Override
                          public void run() {
                              tv_text.setText('111111111111111');
                          }
                      });
                      thread.start();
                  }
              });
          }
      }
      

      當(dāng)點擊按鈕更新UI的時候就會發(fā)現(xiàn)報了異常,異常如下

      圖片.png

      這個異常證明了子線程不能直接更新UI,解決方案如下

      (1)通過Activity中的runOnUIThread方法

      public class MainActivity extends AppCompatActivity { private Button bt_click_me; private TextView tv_text; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt_click_me = findViewById(R.id.bt_click_me); tv_text = findViewById(R.id.tv_text); bt_click_me.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Thread thread = new Thread(new Runnable() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { tv_text.setText('111111111111111'); } }); } }); thread.start(); } }); } }

      我們來深入源碼

      /**
       * Runs the specified action on the UI thread. If the current thread is the UI
       * thread, then the action is executed immediately. If the current thread is
       * not the UI thread, the action is posted to the event queue of the UI thread.
       *
       * @param action the action to run on the UI thread
       */
      public final void runOnUiThread(Runnable action) {
          if (Thread.currentThread() != mUiThread) {
              mHandler.post(action);
          } else {
              action.run();
          }
      }
      

      源碼的意思是說, 如果當(dāng)前線程不是UI線程, 那么執(zhí)行

      mHandler.post(action);

      否則直接執(zhí)行run。

      這個結(jié)論直接告訴了我們,Handler的post方法也能做到從子線程更新UI。

      (2)通過Handler的post方法

      public class MainActivity extends AppCompatActivity {
      
          private Handler handler = new Handler();
      
          private Button bt_click_me;
          private TextView tv_text;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              bt_click_me = findViewById(R.id.bt_click_me);
              tv_text = findViewById(R.id.tv_text);
      
              bt_click_me.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
      
                      Thread thread = new Thread(new Runnable() {
                          @Override
                          public void run() {
                              handler.post(new Runnable() {
                                  @Override
                                  public void run() {
                                      tv_text.setText('111111111111111');
                                  }
                              });
                          }
                      });
                      thread.start();
                  }
              });
          }
      }
      

      我在UI線程中new了一個Handler對象,在子線程中用這個對象來調(diào)用post方法。

      我們來深入源碼

      /** * Causes the Runnable r to be added to the message queue. * The runnable will be run on the thread to which this handler is * attached. * * @param r The Runnable that will be executed. * * @return Returns true if the Runnable was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }

      在Handler對象中,有一個post方法,分析源碼得知, 這個方法將形參r封裝到一個消息里面, 再利用sendMessageDelayed方法將消息發(fā)送(添加)到消息隊列。(注:理解這句話需要對Handler機制有一定的了解)

      我們得出結(jié)論,通過handler發(fā)送消息也能實現(xiàn)子線程更新UI。

      (3)通過handler發(fā)送消息來實現(xiàn)子線程更新UI

      public class MainActivity extends AppCompatActivity {
      
          private Handler handler = new Handler(){
              @Override
              public void handleMessage(Message msg) {
                  super.handleMessage(msg);
                  switch (msg.what){
                      case 1:
                          tv_text.setText('111111111111111');
                          break;
                  }
              }
          };
      
          private Button bt_click_me;
          private TextView tv_text;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              bt_click_me = findViewById(R.id.bt_click_me);
              tv_text = findViewById(R.id.tv_text);
      
              bt_click_me.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
      
                      Thread thread = new Thread(new Runnable() {
                          @Override
                          public void run() {
      
                              Message message = Message.obtain();
                              message.what = 1;
                              handler.sendMessage(message);
      
                          }
                      });
                      thread.start();
                  }
              });
          }
      }
      

      (4)通過view的post方法實現(xiàn)

      public class MainActivity extends AppCompatActivity { private Button bt_click_me; private TextView tv_text; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt_click_me = findViewById(R.id.bt_click_me); tv_text = findViewById(R.id.tv_text); bt_click_me.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Thread thread = new Thread(new Runnable() { @Override public void run() { bt_click_me.post(new Runnable() { @Override public void run() { tv_text.setText('111111111111111'); } }); } }); thread.start(); } }); } }

      我們來深入源碼

      /**
       * <p>Causes the Runnable to be added to the message queue.
       * The runnable will be run on the user interface thread.</p>
       *
       * @param action The Runnable that will be executed.
       *
       * @return Returns true if the Runnable was successfully placed in to the
       *         message queue.  Returns false on failure, usually because the
       *         looper processing the message queue is exiting.
       *
       * @see #postDelayed
       * @see #removeCallbacks
       */
      public boolean post(Runnable action) {
          final AttachInfo attachInfo = mAttachInfo;
          if (attachInfo != null) {
              return attachInfo.mHandler.post(action);
          }
      
          // Postpone the runnable until we know on which thread it needs to run.
          // Assume that the runnable will be successfully placed after attach.
          getRunQueue().post(action);
          return true;
      }
      

      其實最終也調(diào)用了mHandler.post(action)方法。

      第二種場景總結(jié):

      (1)Android從子線程更新UI就是通過Handler來實現(xiàn)的,官方發(fā)明Handler主要就是給我們更新UI用的。

      其實吧, 一些腦洞大開的猿類動物偏不按照常理出牌:

      (1)在子線程中他偏偏不用Handler更新UI?
      public class MainActivity extends AppCompatActivity { private TextView tv_text; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_text = findViewById(R.id.tv_text); tv_text.setText('1111111'); Thread thread = new Thread(new Runnable() { @Override public void run() { for (int i=0;i<500000;i ){ Log.e('aa', String.valueOf(i));//耗時操作 if(i==499999){ tv_text.setText('22222222'); } } } }); thread.start(); } }

      這個例子是從onCreate方法中的子線程更新UI, 其中有耗時操作

      圖片.png

      上述的例子依然報錯, 那么怎么才能不讓他報錯呢,往下看

      public class MainActivity extends AppCompatActivity {
      
          private TextView tv_text;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              tv_text = findViewById(R.id.tv_text);
              tv_text.setText('1111111');
              Thread thread = new Thread(new Runnable() {
                          @Override
                          public void run() {
                              tv_text.setText('22222222');
                          }
                      });
              thread.start();
          }
      }
      

      當(dāng)我去除耗時操作時,就不會報這個錯誤了,那么為什么呢?

      我們來翻看源碼

      在ViewRootImpl類中找到了這個方法,這個方法就是之所以報錯的根本

      void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( 'Only the original thread that created a view hierarchy can touch its views.'); } }

      而ViewRootImpl對象是在執(zhí)行到onResume才創(chuàng)建時的,所以得出結(jié)論,onCreate中的子線程如果不是耗時操作,基本都是可以更新UI的,但不能保證。因為一個是UI線程,一個是子線程,我們誰也不知道哪個線程更快一些。

      (2)把消息從UI線程發(fā)送到子線程?
      public class MainActivity extends AppCompatActivity {
      
          private Button bt_click_me;
          private Handler handler;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              bt_click_me = findViewById(R.id.bt_click_me);
      
              bt_click_me.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      Message message = Message.obtain();
                      message.what = 1;
                      handler.sendMessage(message);
                  }
              });
      
              Thread thread = new Thread(new Runnable() {
                  @Override
                  public void run() {
                      Looper.prepare();
                      Looper looper = Looper.myLooper();
                      handler = new Handler(looper){
                          @Override
                          public void handleMessage(Message msg) {
                              super.handleMessage(msg);
                              Log.d('aa', '11111');
                          }
                      };
                      Looper.loop();
                  }
              });
              thread.start();
          }
      }
      

      UI線程本身就有Looper,但是子線程是沒有Looper的,所以必須新建Looper來輪詢Looper中的消息隊列。

      ? 著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多