Android-非MainActivity中子线程更新UI

我是刚学习安卓开发,小白一个,很多知识都不懂,查了一些资料才弄明白的,我想应该也有一些同学,刚开始时候也会无从下手。通过这篇文章记录下来,也方便以后查阅。

开发工具:Androit Studio 3.2.1

一 、相关资料

1.Android OKHttp使用详解
2.使用handler ui线程和子线程通讯更新ui示例
3.项目demo下载

二、添加引用和权限
1.创建一个Activity to Mobile 为Empty Avtivity的项目

2.为App添加连网权限(必须添加,否则使用okhttp时候App会崩溃,软件编译阶段正常,使用时候就会崩溃,搞了半天才明白没有添加连网权限)
在AndroidManifest.xml文件中添加

3.添加okHttp依赖库
在build.gradle文件中(这个文件名可能有两个,选择文件名有Module:app字样的文件)添加代码

    implementation 'com.squareup.okhttp3:okhttp:3.8.1'
    implementation 'com.squareup.okio:okio:1.7.0'

上面的代码添加在

dependencies {
代码区
}

基本配置完毕。

三、源代码
1.在MainActivity.java类中


package com.androiduiupdemo;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
   private Button button;
   private String mBtnTitle = "";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button)findViewById(R.id.button);
        button.setOnClickListener(this);

    }

    /*  重要
        更新UI操作
     */
    public Handler mHandler=new Handler(){
        public void handleMessage(Message msg){  //此方法在UI线程中运行(需放到MainActivity.java中)
            switch(msg.what){
                case 1:
                    EditText mTxt1 = (EditText)findViewById(R.id.txt1);
                   mTxt1.setText(msg.getData().getString("m")); // msg.getData().getString("my")获取子线程传过来 '键名' 为my对应的信息,并设置控件UI
                   mBtnTitle +=  " 异步 ";
                   button.setText(mBtnTitle);
                    break;
                case 2:
                    EditText mTxt2 = (EditText)findViewById(R.id.txt2);
                    mTxt2.setText(msg.getData().getString("my")); // msg.getData().getString("my")获取子线程传过来 '键名' 为my对应的信息,并设置控件UI
                    mBtnTitle += " 同步 ";
                    button.setText(mBtnTitle);
                    break;
            }
        }

    };

    @Override
    public void onClick(View v) {
        if(v.getId() == R.id.button){
            Toast.makeText(this,"test",Toast.LENGTH_LONG).show();
            myTest mytest = new myTest(this);    //实例化myTest类
            mytest.getDataAsyn("http://baidu.com",1); //调用异步请求
            mytest.getDataSyn("http://qq.com",2);     //调用同步请求
        }
    }
}

2.新创建一个类文件,名字为myTest
在myTest.java中用到okHttp类库的异步和同步请求方法,具体区别请查阅文章头部的相关资料

package com.androiduiupdemo;

import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class myTest {

    private  MainActivity mActivity;
    public  myTest(MainActivity mainActivity){ //将主线程类传进来,后面向UI线程发送消息时候需要
        this.mActivity = mainActivity;
    }

    /*异步获取网页源码 需要用到okHttp类库
    *参数String url  访问的网站
    * 参数int i  识别码 switch case中需要用到
    */
    public void getDataAsyn(final String url , final int i) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)  //设置访问网址
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if(response.isSuccessful()){//回调的方法执行在子线程。
                    String mResult = response.body().string();  //获取网页返回内容
                    Log.d("myTs","异步获取数据成功了");
                    Log.d("myTs","response.code()=="+response.code());
                    Log.d("myTs","response.body().string()==" + mResult );

                    //向UI线程发送消息
                    Message msg =  new Message();
                    Bundle mdata = new Bundle();
                    mdata.putString("my",mResult);             //这里的数据是 ‘键 => 值’ 类型的对应,在MainActivity.java的handleMessage方法中使用
                    msg.setData(mdata);
                    msg.what = i;                            //i的值由参数传进来,用于在MainActivity.java的handleMessage方法中识别执行哪一个case 语句,  当然i的类型可以定义成其它的。
                    mActivity.mHandler.sendMessage(msg);     //向主UI线程发送消息,不在MainActivity的线程需要 调用主类名才可以发送消息给主UI线程
                }
            }
        });
    }

    /*同步获取网页源码 需要用到okHttp类库
     *参数String url  访问的网站
     * 参数int i  识别码 在switch case中需要用到
     */
    public void getDataSyn(final String url,final int i){
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象
                    Request request = new Request.Builder()
                            .url(url)//请求接口。如果需要传参拼接到接口后面。
                            .build();//创建Request 对象
                    Response response = client.newCall(request).execute();//得到Response 对象
                    if (response.isSuccessful()) {
                        String mResult = response.body().string();
                        Log.d("kwwl","response.code()=="+response.code());
                        Log.d("kwwl","response.message()=="+response.message());
                        Log.d("kwwl","res==" + mResult);

                        //向UI线程发送消息
                        Message msg =  new Message();
                        Bundle mdata = new Bundle();
                        mdata.putString("my",mResult);       //这里的数据是 ‘键 => 值’ 类型的对应,在MainActivity.java的handleMessage方法中使用
                        msg.setData(mdata);
                        msg.what = i;                       //i的值由参数传进来,用于在MainActivity.java的handleMessage方法中识别执行哪一个case 语句,  当然i的类型可以定义成其它的。
                        mActivity.mHandler.sendMessage(msg);  //向主UI线程发送消息,不在MainActivity中类里面创建的线程,需要调用主类名才可以发送消息给主UI线程
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

3.主界面图,点击‘获取数据’会通过网络线程获取源码,并且更新两个EditText文本框信息
Android-非MainActivity中子线程更新UI_第1张图片

Android-非MainActivity中子线程更新UI_第2张图片

你可能感兴趣的:(Android)