android 橘子汁 在子线程中更新主线程UI 困扰

        问题描述:要做这么一个功能,从网上获取一些数据,数据内容未获取到前显示一张图片(等待图片,但不是progressbar),一旦数据获取成功就通知主UI,使其为listView

        这两天都在搞这个问题,用尽线程无数,始终无法解决诸如线程安全和4.0网络线程问题。

        最开始,我将网络线程与UI主线程放在一起,可总是报android.os.NetworkOnMainThreadException 错误,更别提更新UI了!貌似这是因为android高版本为了优化类似主UI进程长时间等待所做的改变。在8以下的版本中都没有这样的问题。

        后来,我将网络线程独立出来。启用一个网络线程用于控制网络数据获取和获取成功后的UI更新。可是问题又来了:新启动的网络线程中根本无法操作主线程里的UI。连context都传不进来。会报类似这样的错误android.view.ViewRoot$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views.

 

        终于,为了解决这些问题,我最终还是回归了android系统中的handler。使用handler来解决这个问题就简单多了。

       步骤:

                1.开始onCreate中设置等待UI

                2.启动网络连接获取数据线程,此线程中将获得的数据赋值给主类全局数据参数,判断是否获取数据成功,成功则通知ui更新(向主UI线程的handler对象send一个msg)

                3.在主UI线程中监视handler的msg,若发现msg被更改为预设情况,则更新ui

 

奉上代码:

苹果橘子问题是一个经典的多线程同步问题,假设有一个篮子,里面装有若干个苹果和橘子,现在有两个人要从篮子里取出水果,一个人只能拿苹果,另一个人只能拿橘子,直到篮子里的水果被取完为止。 Java可以使用wait()和notify()方法来实现多线程同步,具体实现如下: ``` public class Basket { private int appleCount; // 苹果数量 private int orangeCount; // 橘子数量 public synchronized void getApple() { while (appleCount == 0) { try { wait(); // 等待苹果 } catch (InterruptedException e) { e.printStackTrace(); } } appleCount--; System.out.println("取出一个苹果,还剩" + appleCount + "个苹果"); notifyAll(); // 唤醒其他线程 } public synchronized void getOrange() { while (orangeCount == 0) { try { wait(); // 等待橘子 } catch (InterruptedException e) { e.printStackTrace(); } } orangeCount--; System.out.println("取出一个橘子,还剩" + orangeCount + "个橘子"); notifyAll(); // 唤醒其他线程 } public synchronized void put(String fruit, int count) { if ("apple".equals(fruit)) { appleCount += count; System.out.println("放入" + count + "个苹果,还剩" + appleCount + "个苹果"); } else if ("orange".equals(fruit)) { orangeCount += count; System.out.println("放入" + count + "个橘子,还剩" + orangeCount + "个橘子"); } notifyAll(); // 唤醒其他线程 } } public class AppleThread extends Thread { private Basket basket; public AppleThread(Basket basket) { this.basket = basket; } @Override public void run() { while (true) { basket.getApple(); } } } public class OrangeThread extends Thread { private Basket basket; public OrangeThread(Basket basket) { this.basket = basket; } @Override public void run() { while (true) { basket.getOrange(); } } } public class Main { public static void main(String[] args) { Basket basket = new Basket(); new AppleThread(basket).start(); new OrangeThread(basket).start(); for (int i = 0; i < 10; i++) { basket.put("apple", 1); basket.put("orange", 1); } } } ``` 在上面的代码,Basket类是共享资源,getApple()和getOrange()方法是消费者线程,put()方法是生产者线程。当苹果或橘子被取走后,消费者线程会调用notifyAll()方法来唤醒其他线程,生产者线程在放入水果时也会调用notifyAll()方法来唤醒其他线程。通过wait()和notify()方法的配合,可以实现多线程同步,保证线程安全。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值