• android4.0以上访问网络不能在主线程中进行以及在线程中操作UI的解决方法


    MONO 调用一个线程操作UI 然后报Only the original thread that created a view hierarchy can touch its views。错误 google了一下说UI的操作还是需要到主线程,看了些java的例子 java中是使用了Handler 但是在MONO中需要怎么实现?

    一.

    RunOnUiThread(()=>执行语句  );

    demo:

    this.RunOnUiThread(() => tv.Text = "records: " + twt.Count.ToString());

    二.

    Handler实现也是可以的,关键代码
            private Handler handler = new Handler();
            Java.Lang.Runnable rb;
    protected override void OnCreate(Bundle bundle){
                            rb = new Java.Lang.Runnable(() => {
                                button.Text = string.Format("{0} Runnable!", count++);
                                handler.PostDelayed(rb, 1000);
                            });
                            handler.PostDelayed(rb, 1000);}

    三.其他方式

    刚刚上手android,在写一个利用Socket与服务器端进行通信的Demo时候报了一个android.os.NetworkOnMainThreadException的异常:

    服务器端:

    public class SimpleServer {

    public static void main(String[] args){

    try {

    ServerSocket ss=new ServerSocket(40000);

    System.out.println("等待连接......");

    while(true){

    Socket s=ss.accept();

    OutputStream os=s.getOutputStream();

    os.write("hello".getBytes("utf-8"));

    os.close();

    s.close();

    }

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    求助度娘后发现是SDK的版本问题,android4.0中访问网络不能在主程序中进行,行吧,那就老老实实的重新开启一个线程:

    new Thread(){

    public void run(){

    try {

    Socket s=new Socket("172.22.16.26", 40000);

    BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));

    String line=br.readLine();

    show.setText("服务器说:"+line);

    br.close();

    s.close();

    } catch (UnknownHostException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }.start();

    结果又报了异常:

    android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

    相信各位已经看出了在下犯了一个很低级的错误:在新启的线程中操作UI,UI线程是非线程安全的,Android平台不允许Activity新启动的线程访问该Activity里的界面组件,这时就要借助Handler的消息传递机制了:

    new Thread(){

    public void run(){

    try {

    Socket s=new Socket("172.18.6.26",40000);

    BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));

    String line=br.readLine();

    //System.out.println("服务器说:"+line);

    Message msg=new Message();

    msg.what=0x123;

    msg.obj=line;

    myhandler.sendMessage(msg);

    br.close();

    s.close();

    } catch (UnknownHostException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }.start();

    然后重写handlerMessage方法获取消息:

    final Handler myhandler=new Handler(){

    public void handleMessage(Message msg){

    if(msg.what==0x123){

    System.out.println("--------------->"+msg.obj);

    show2.setText((String)msg.obj);

    }

    }

    };

    当新线程发送消息时,该方法自动被调用,handlerMessage(Message msg)方法依旧位于主线程中,所以可以动态的修改UI组件。

    网络连接不能放在主线程
           android 4.0 以上    网络连接不能放在主线程
           4.0 以下 好像可以

    RLZH~UWUX47AJ%ZY1~QPC_T

    Q$0TQ)}A@~O3WL)MSS~D)GV

    在Android4.0以后,会发现,只要是写在主线程(就是Activity)中的HTTP请求,运行时都会报错,这是因为Android在4.0以后为了防止应用的ANR(aplication Not Response)异常,即使这里表达不是很清晰,大家应该都明白吧,哈哈

    就针对此问题有两种解决的方法:

    1.可以再Activity的onCreate()方法中加入这样一段代码,如下:

    JAVA

    if (Build.VERSION.SDK_INT >= 11) {
    StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads  ().detectDiskWrites().detectNetwork().penaltyLog().build());
    StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());
    }

    Mono 版

    if (Build.VERSION.SdkInt.GetHashCode()>=11)
                {
                    StrictMode.SetThreadPolicy(new StrictMode.ThreadPolicy.Builder().DetectDiskReads().DetectDiskWrites().DetectNetwork().PenaltyLog().Build());
                    StrictMode.SetVmPolicy(new StrictMode.VmPolicy.Builder().DetectLeakedSqlLiteObjects().DetectLeakedClosableObjects().PenaltyLog().PenaltyDeath().Build());
                }


    后就可以在主线程中进行网络操作了

    2.一般情况我们应该这样做

    启动一条子线程进行你的网络请求。

    当然,如果你的应用程序执行的网络请求数据量很小的话,可以使用第一种方案

  • 相关阅读:
    BZOJ:4219: 跑得比谁都快 3007: 拯救小云公主
    BZOJ:4816: [Sdoi2017]数字表格
    BZOJ:4333: JSOI2012 智者的考验
    BZOJ:3911: SGU383 Caravans(三角剖分)
    bzoj:2595: [Wc2008]游览计划
    ZOJ3602:Count the Trees
    A Dangerous Maze (II) LightOJ
    Where to Run LightOJ
    Lights inside 3D Grid LightOJ
    Snakes and Ladders LightOJ
  • 原文地址:https://www.cnblogs.com/laxknight/p/3347009.html
Copyright © 2020-2023  润新知