Aren的HANDLER是否有自己的主线?

时间:2015-12-13 20:11:27

标签: android multithreading

我现在真的很沮丧。

我尝试进行套接字连接,但我总是遇到NetworkOnMainThread异常。

我的目标是创建一个具有线程,套接字和Messenger模型的对象,以便专门使用该对象进行通信,如下所示:

WebBridge wb = new WebBridge(); 
wb.Send("My data to send", myLocalMessengerForAnswer);

我尝试使用具有相同结果的Handler。我也试过这个,用自己的Handler创建自己的线程,但没有成功。

Aren的处理程序是否拥有自己的Thread?如果我应该在Handler的线程中,为什么我会收到NetworkInMainThread异常?

提前致谢。

public class WebBridge {
    private class WebBridgeThread extends Thread {
    static final int STARTUP = 1;

    public Handler handler;
    Socket socket;

    public WebBridgeThread() {
        super("WebBridgeThread");
    }

    @Override
    public void run() {
        Looper.prepare();
        handler = new Handler() {
            @Override
            public void dispatchMessage(Message msg) {
                // TODO Auto-generated method stub
                super.dispatchMessage(msg);
                switch(msg.what) {
                    case STARTUP:
                    try {
                        socket = new Socket("192.168.100.99",1234);
                        int fer = 5;
                    } catch (UnknownHostException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    break;
                }
            }
        };
        Looper.loop();
    }


}


public WebBridge(Context paramContext) {
    WebBridgeThread wbt = new WebBridgeThread();
    wbt.start();
    Message msg = new Message();
    msg.what = WebBridgeThread.STARTUP;
    wbt.handler.dispatchMessage(msg);
}

1 个答案:

答案 0 :(得分:3)

  

如果我应该在Handler的线程中,为什么我会收到NetworkInMainThread异常?

如果您检查public class PlacesMapActivity extends MapActivity { PlacesList nearPlaces; MapView mapView; List<Overlay> mapOverlays; AddItemizedOverlay itemizedOverlay; GeoPoint geoPoint; MapController mc; double latitude; double longitude; OverlayItem overlayitem; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_places_map); Intent i = getIntent(); String user_latitude = i.getStringExtra("user_latitude"); String user_longitude = i.getStringExtra("user_longitude"); nearPlaces = (PlacesList) i.getSerializableExtra("near_places"); mapView = (MapView) findViewById(R.id.mapView); mapView.setBuiltInZoomControls(true); mapOverlays = mapView.getOverlays(); geoPoint = new GeoPoint((int) (Double.parseDouble(user_latitude) * 1E6), (int) (Double.parseDouble(user_longitude) * 1E6)); Drawable drawable_user = this.getResources() .getDrawable(R.drawable.mark_red); itemizedOverlay = new AddItemizedOverlay(drawable_user, this); overlayitem = new OverlayItem(geoPoint, "Your Location", "That is you!"); itemizedOverlay.addOverlay(overlayitem); mapOverlays.add(itemizedOverlay); itemizedOverlay.populateNow(); Drawable drawable = this.getResources() .getDrawable(R.drawable.mark_blue); itemizedOverlay = new AddItemizedOverlay(drawable, this); mc = mapView.getController(); int minLat = Integer.MAX_VALUE; int minLong = Integer.MAX_VALUE; int maxLat = Integer.MIN_VALUE; int maxLong = Integer.MIN_VALUE; if (nearPlaces.results != null) { // loop through all the places for (Place place : nearPlaces.results) { latitude = place.geometry.location.lat; // latitude longitude = place.geometry.location.lng; // longitude geoPoint = new GeoPoint((int) (latitude * 1E6), (int) (longitude * 1E6)); overlayitem = new OverlayItem(geoPoint, place.name, place.vicinity); itemizedOverlay.addOverlay(overlayitem); // calculating map boundary area minLat = (int) Math.min( geoPoint.getLatitudeE6(), minLat ); minLong = (int) Math.min( geoPoint.getLongitudeE6(), minLong); maxLat = (int) Math.max( geoPoint.getLatitudeE6(), maxLat ); maxLong = (int) Math.max( geoPoint.getLongitudeE6(), maxLong ); } mapOverlays.add(itemizedOverlay); // showing all overlay items itemizedOverlay.populateNow(); } mapView.getController().zoomToSpan(Math.abs( minLat - maxLat ), Math.abs( minLong - maxLong )); mc.animateTo(new GeoPoint((maxLat + minLat)/2, (maxLong + minLong)/2 )); mapView.postInvalidate(); } @Override protected boolean isRouteDisplayed() { return false; } } 的代码,您会看到Handler基本上调用dispatchMessage(),这意味着它会在当前线程上运行,即您的案例中的UI线程。

相反,如果你调用handleMessage(),处理程序会将消息排入队列并使用looper在线程上运行sendMessage()中的逻辑,即你的情况下的后台线程。 (在队列handleMessage()之后直接调用队列中的消息后调用Looper.loop();这里当前线程是带有looper的线程)

所以你需要

  1. 使用dispatchMessage()中的sendMessage()代替WebBridge()
  2. dispatchMessage()
  3. 中覆盖handleMessage()而不是dispatchMessage()

    将线程优先级设置为后台也是一个好主意,所以你不会在UI线程中赢得这么多。

    顺便说一句,您还可以使用Handler为您完成艰苦的工作,它会创建一个新线程并设置其优先级。然后,在启动之后,您可以获取其looper(HandlerThread)并将其推送到处理程序的构造函数中。您仍然需要在网络逻辑的处理程序中覆盖getLooper()