在子线程中更新类变量然后使用该变量来更新控件属性导致第二次才显示

问题:

初学者在使用联网操作时,如果基础没打好,可能出以下差错:
在子线程中更新类变量,然后使用该变量来更新控件属性,第一次控件是没反应的,第二次控件的属性才被更新。
请看示例代码:
示例里面有个类变量data,整个demo的逻辑就是点击Button后开启子线程发起post请求,将数据赋值给data,然后在子线程操作完后把类变量里面的东西更新给Textview

public class MainActivity extends AppCompatActivity {
    Button send;
    TextView textView;
    String data;

    void initView(){
        send = (Button) findViewById(R.id.send);
        textView = (TextView) findViewById(R.id.text_view);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();

        send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {

                       try{
                            // Post request example:
                            OkHttpClient client = new OkHttpClient();
                            RequestBody requestBody = new FormBody.Builder()
                                    .build();
                            Request request = new Request.Builder()
                                    .url("https://www.baidu.com")
                                    .post(requestBody)
                                    .build();
                            Response response = client.newCall(request).execute();

                            data = response.body().string();
                            System.out.println(data);
                        } catch (Exception e){
                            e.printStackTrace();
                        }

                    }
                }).start();

                textView.setText(data);

            }
        });

    }

}

如何解决:

当数据取得后,随后回到主线程,直接把取得的数据赋值更新给控件。

public class MainActivity extends AppCompatActivity {
    Button send;
    TextView textView;
    //String data;


    void initView(){
        send = (Button) findViewById(R.id.send);
        textView = (TextView) findViewById(R.id.text_view);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();

        send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try{
                            // Post request example:
                            OkHttpClient client = new OkHttpClient();
                            RequestBody requestBody = new FormBody.Builder()
                                    .build();

                            Request request = new Request.Builder()
                                    .url("https://www.baidu.com")
                                    .post(requestBody)
                                    .build();

                            Response response = client.newCall(request).execute();
                            String data = response.body().string();
                            
                            switchThread(data);
                            System.out.println(data);

                        } catch (Exception e){
                            e.printStackTrace();
                        }

                    }
                }).start();
            }
        });

    }

    private void switchThread(final String content){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                textView.setText(content);
            }
        });

    }

}

原因:

第一次更新失败是因为某ui控件尚未被赋值,类变量仍然为空;第二次更新成功是因为连续开启了两个子线程(第二次点击开启了第二个子线程),当第二个子线程开启时候第一个子线程便被终止,子线程内的成员变量赋值给类变量,ui控件获得值后便被更新成功

总结:

对于初学者而言,HandlerrunOnUiThread()Thread等是其永远绕不开的东西,因此不要想着偷来用巧方法,否则会弄巧成拙。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值