如何更新线程中的引用和活动?

Posted

技术标签:

【中文标题】如何更新线程中的引用和活动?【英文标题】:How can i update the reference of and activity in a thread? 【发布时间】:2018-11-05 22:59:24 【问题描述】:

我有一个线程正在运行并向服务器发出请求,并根据服务器的响应更改应用程序中几个元素的颜色。问题是:我需要更改活动,并且线程必须继续运行才能在这个新活动中发出请求,但是当我进入需要再次为这些元素着色的主要活动时,它不会绘制它们。我知道这是因为当线程第一次在主活动中创建时,它有一个对保持在威胁范围内的主活动的引用,当我离开活动时它会破坏它,然后当我回来时引用是新的,但引用我在线程上工作的活动是旧的,因为我在调试模式下测试并发现了这一点。

线程的代码是这个:

    public void initiateThreads(final boolean fromDisplayThread)


            if(!fromDisplay)
            t1= new Thread(new Runnable() 
                @Override
                public void run() 
                    final TextView text=(TextView) findViewById(R.id.textView);
                    final Timer timer = new Timer();
                    timer.schedule(new TimerTask() 


                        @Override
                        public void run() 

                            String url = "XX.XX.XX.XX";

                            Log.i("DREG", "onLoadMoreItems: " + url);

                            final StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
                                    new Response.Listener<String>() 
                                        @Override
                                        public void onResponse(String response) 
                                            System.out.println(response);
                                            text.setText(response);

                                            try 

                                                JSONObject res = new JSONObject(response);
                                                String FRONT = res.getString("FRONT");
                                                String BACK= res.getString("BACK");
                                                String LEFT = res.getString("LEFT");
                                                String RIGHT = res.getString("RIGHT");

                                                setWarningLevel(FRONT, BACK, LEFT, RIGHT);

                                                setDelay();

                                                visualWarning(FRONT, BACK, LEFT, RIGHT);
                                             catch (final JSONException e) 
                                                text.setText(e);
                                                Log.e(TAG, "Json parsing error: " + e.getMessage());
                                                runOnUiThread(new Runnable() 
                                                    @Override
                                                    public void run() 
                                                        Toast.makeText(getApplicationContext(),
                                                                "Json parsing error: " + e.getMessage(),
                                                                Toast.LENGTH_LONG)
                                                                .show();
                                                    
                                                );

                                            
                                        
                                    ,
                                    new Response.ErrorListener() 
                                        @Override
                                        public void onErrorResponse(VolleyError error) 
                                            if (error instanceof NetworkError) 
                                             else if (error instanceof ServerError) 
                                             else if (error instanceof AuthFailureError) 
                                             else if (error instanceof ParseError) 
                                             else if (error instanceof NoConnectionError) 
                                             else if (error instanceof TimeoutError) 
                                                Toast.makeText(getApplicationContext(),
                                                        "Oops. Timeout error!",
                                                        Toast.LENGTH_LONG).show();
                                                text.setText(error);
                                            
                                        
                                    
                            );
                            stringRequest.setRetryPolicy(new DefaultRetryPolicy(
                                    10000,
                                    DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                                    DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
                            RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);
                            requestQueue.add(stringRequest);
                        
                    , 0, 2000);

                
            );
            t1.start();

绘制元素的函数是visualWarning(),代码是:

 public void visualWarning(String FRONT, String BACK, String LEFT, String RIGHT)


            switch (FRONT) //FRONT
            case "NONE":
                ImageView imageViewIcon1 = (ImageView) findViewById(R.id.imageView1);
                imageViewIcon1.setColorFilter(Color.parseColor("#0000D3"));

                ImageView imageViewIcon2 = (ImageView) findViewById(R.id.imageView2);
                imageViewIcon2.setColorFilter(Color.parseColor("#0000D3"));

                ImageView imageViewIcon3 = (ImageView) findViewById(R.id.imageView3);
                imageViewIcon3.setColorFilter(Color.parseColor("#0000D3"));

                ImageView imageViewIcon4 = (ImageView) findViewById(R.id.imageView4);
                imageViewIcon4.setColorFilter(Color.parseColor("#0000D3"));


//SWITCH STAEMENT CONTINUES BUT IT'S ALL THE SAME JUST CHANGING COLOR


如何更新当前在线程中运行的活动?

【问题讨论】:

【参考方案1】:

在后台线程中保留对活动的引用通常是不好的。您需要的是事件,您可以使用 LocalBroadcasts,每当您从服务器接收数据时向您的活动发送广播,您将在正在运行的活动中收到广播。

确保在活动的 onDestroy 中取消注册广播

【讨论】:

【参考方案2】:

使用runOnUiThread 在主线程上执行您的部分代码

public void onResponse(String response) 
    try 
        ....
        runOnUiThread(() -> visualWarning(FRONT, BACK, LEFT, RIGHT));
    

【讨论】:

以上是关于如何更新线程中的引用和活动?的主要内容,如果未能解决你的问题,请参考以下文章

更新原始活动中的集成进度条

所有活动 ThreadLocal<T> 和 [ThreadStatic] 引用的列表

如何在第一个活动中更新回收站视图,同时更改其他活动中的数据?

如何优雅地关闭 Android 应用程序中的所有活动并关闭所有正在运行的线程?

如何更改图像并在 5 秒后重新运行线程中的主要活动后不回到 android 中的基本布局

如何在无限循环中不断更新活动中的 TextView?