zoukankan      html  css  js  c++  java
  • Android笔记(二十九) Android中的异步更新(一) Android中的线程

    Java中的线程

    1. 线程的两种实现方式

             ①继承Thread类

             ②实现Runnable接口

             两者区别在于,Thread这个类的对象,代表的是一个线程,而Runnable的对象,代表的是线程体(也就是线程要执行的代码)。

    2.线程的生命周期

             创建---调用start()进入就绪状态---抢占到CPU就开始进入运行状态---运行过程中被别的线程抢到CPU,或者遇到阻塞,则进入就绪状态---如果执行完线程体,则进入死亡状态

             线程死亡之后,不可能再复活。

    3.多线程同步

             如果多个线程访问同一个资源,会产生多个线程竞争一个资源,则会产生多线程错误,这时需要通过同步方式来解决,使用synchronized关键字,采用同步代码块或者同步方法。

             所谓的同步,就是指在一个线程访问资源时,别的线程是无法访问这个资源的。

    MainThread和WorkerThread

             Android中可以将线程分为:MainThread和WorkerThread两大类

             MainThread就是主线程,又称为UI线程,所有和UI相关的代码,都是运行在MainThread中的。

             除了MainThread之外的线程,都是WorkerThread,原则上来讲WorkerThread是不允许操作UI组件的。

    Android当中线程的使用

             实现一个demo,要求实现点击按钮5秒钟之后,改变TextView的文字。

    package cn.lixyz.handlertest;
    
    import android.app.Activity;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
        private TextView textView;
        private Button button;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
    
            textView = (TextView) findViewById(R.id.text);
            button = (Button) findViewById(R.id.button);
    
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    new Thread(){
                        @Override
                        public void run() {
                            super.run();
                            try {
                                sleep(5000);
                                textView.setText("改变之后的文字");
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }.start();
                }
            });
        }
    }
    MainActivity.java
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="30dp"
            android:text="@string/hello_world"
            android:textSize="50dp" />
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="30dp"
            android:text="点击我改变文字" />
    
    </LinearLayout>
    activity_main.xml

          像上面一样编码的话,点击按钮5秒之后,会提示错误:

    并抛出异常:

    09-15 03:28:33.964    5854-6002/cn.lixyz.handlertest E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-112
        Process: cn.lixyz.handlertest, PID: 5854
        android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
                at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6024)
                at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:820)
    ......

          上面的代码和异常证明了,Android是不允许非UI线程去修改UI组件的。

          但是也有例外,譬如ProgressBar,看代码

    package cn.lixyz.handlertest;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ProgressBar;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
        private ProgressBar progressBar;
        private Button button;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
    
            progressBar = (ProgressBar) findViewById(R.id.progressBar);
            button = (Button) findViewById(R.id.button);
    
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    new Thread() {
                        @Override
                        public void run() {
                            super.run();
                            for (int i = 0; i < 100; i++) {
                                try {
                                    sleep(100);
                                    progressBar.setProgress(i);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
    
                        }
                    }.start();
                }
            });
        }
    }
    MainActivity.java
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <ProgressBar
            android:id="@+id/progressBar"
            style="@style/Widget.AppCompat.ProgressBar.Horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="10dp" />
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="30dp"
            android:text="点击开始加载" />
    
    </LinearLayout>
    activity_main.xml

             运行结果:

             所以说:大多数情况下,在WorkerThread中是无法修改UI的,只有少数情况下才可以。

             那么可以不可以把所有修改UI的代码全部放在MainThread中执行呢?答案是否定的。

             在一个应用程序之中,主线程通常用于接收用户的输入,以及将运算的结果反馈给用户,后台运行耗时代码则会导致主线程阻塞,程序无法相应,也就是常见的ANR(application not responding),应用程序没有相应。

             所以说,对于一些可能产生阻塞的操作,必须放到WorkerThread中,这时候就产生了WorkerThread和MainThread的通信问题。

  • 相关阅读:
    假期学习总结2-14
    假期学习总结2-13
    假期总结2-12
    假期总结2-11
    读人月神话
    冲刺第五天 11.29 THU
    冲刺第四天 11.28 WED
    冲刺第三天 11.27 TUE
    冲刺第二天 11.26 MON
    冲刺第一天 11.23 FRI
  • 原文地址:https://www.cnblogs.com/xs104/p/4810970.html
Copyright © 2011-2022 走看看