一般而言,Android的子线程中如果要显示UI相关,需要在显示的前后添加Looper.prepare和Looper.loop.但是实践中发现点问题,代码如下,并且把问题标志出来了。在第一个子线程MyThread2开头可以显示对话框,但是后面的对话框以及MyThread3中用同样方法却显示不了。
   网上说应该只有一个Looper处理消息循环,但是我的多个子线程中均要在多处显示对话框该怎么办。而且我通过handmessage在UI现场中处理消息并显示对话框,也没显示出来。不知道是怎么回事?package com.example.testusb;import java.nio.ByteBuffer;
import java.util.HashMap;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbRequest;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.os.*;public class TestUSB extends Activity { private Button button,button2;
private UsbManager usbManager;
private UsbDevice usbDevice;
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
private PendingIntent pendingIntent;

Intent intent;
StringBuffer sb = new StringBuffer();
private TextView info;

private Handler handler = new Handler(){
@Override


public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case 3:
createAlert("TestUSB","33333333333333333");----------------------------------------这两个地方均没有显示出对话框或者toast
Toast.makeText(TestUSB.this, "33333333333333333", 1000).show();
break;
case 4:
createAlert("TestUSB","44444444444444444");
Toast.makeText(TestUSB.this, "44444444444444444", 1000).show();
break; }
}
};

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_l);

button = (Button) findViewById(R.id.button);
usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);

pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);


button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {

// TODO Auto-generated method stub
new MyThread2().start();
}
});


}

class MyThread2 extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
Looper.prepare();
createAlert("Waring","MyThread2 start");----------------------------------------------这个地方的对话框可以显示出来
Looper.loop();

try {

HashMap<String, UsbDevice> map = usbManager.getDeviceList();
if (map.isEmpty()) {
Looper.prepare();
createAlert("Waring","Empty devicelist");------------------------这个地方和以下所有调用createAlert的地方对话框均显示不出来
 Looper.loop();
}
else
{
for(UsbDevice device : map.values()){

Log.e("device", "vid:"+device.getVendorId()+"   pid:"+device.getProductId()+"   "+device.getDeviceName());

if(5334 == device.getVendorId())
{
usbDevice = device;
}
 createAlert("Warning","vid:"+device.getVendorId()+"   pid:"+device.getProductId()+"   "+device.getDeviceName());
}


if(usbManager.hasPermission(usbDevice)){
handler.sendEmptyMessage(3);

Looper.prepare();
createAlert("Waring","MyThread3 start");
Looper.loop();

new MyThread3().start();
}else{

handler.sendEmptyMessage(4);

Looper.prepare();
createAlert("Waring","requestPermission");
Looper.loop();

usbManager.requestPermission(usbDevice, pendingIntent); 
}
}








/* for(UsbDevice device : map.values()){
sb.append( "vid:"+device.getVendorId()+"   pid:"+device.getProductId()+"   "+device.getDeviceName());
sb.append("\n");
info.setText(sb);
Log.e("device", "vid:"+device.getVendorId()+"   pid:"+device.getProductId()+"   "+device.getDeviceName());
//VendorID 鍜?ProductID  鍗佽繘鍒?
// if(5334 == device.getVendorId() && 12290 == device.getProductId())
if(5334 == device.getVendorId())
{
usbDevice = device;
}
 createAlert("Warning","vid:"+device.getVendorId()+"   pid:"+device.getProductId()+"   "+device.getDeviceName());
}


if(usbManager.hasPermission(usbDevice)){
handler.sendEmptyMessage(3);
sb.append("MyThread3 start");
sb.append("\n");
info.setText(sb);
Looper.prepare();
createAlert("Waring","MyThread3 start");
Looper.loop();

new MyThread3().start();
}else{

handler.sendEmptyMessage(4);
sb.append("requestPermission");
sb.append("\n");
info.setText(sb);
Looper.prepare();
createAlert("Waring","requestPermission");
Looper.loop();
usbManager.requestPermission(usbDevice, pendingIntent); 
}*/

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

class MyThread3 extends Thread{
@Override
public void run() {

 
 
 Looper.prepare();  
 
 createAlert("Warning","My thread3 receive data");
 Looper.loop();
 



}


private void createAlert(String strTitle, String strMsg) {
Dialog alertDialog = new AlertDialog.Builder(TestUSB.this)
.setTitle(strTitle).setMessage(strMsg)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// TODO Auto-generated method stub
setResult(RESULT_OK, intent);
//finish();
}
}).create(); alertDialog.show();
}

private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {     public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.e( "action", action);
        sb.append("action start");
sb.append("\n");
info.setText(sb);
        
        if (ACTION_USB_PERMISSION.equals(action)) {
            synchronized (this) {
                usbDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                 handler.sendEmptyMessage(1);
                    if(usbDevice != null){
                    sb.append("BroadcastReceiver MyThread3 start");
     sb.append("\n");
     info.setText(sb);                       
                     new MyThread3().start();
                   }
                } 
                else {
                 sb.append("permission denied for device"+usbDevice.toString());
     sb.append("\n");
     info.setText(sb);
                    Log.d("denied", "permission denied for device " + usbDevice);
                }
            }
        }
    }
   };}

解决方案 »

  1.   

    另外,在Looper.loop()之后添加Looper.myLooper().quit()也没有用
      

  2.   

    Looper.loop();之后就进入了消息循环,你要调用quit()才会退出,所以你Looper.loop();之后的代码都没有执行到。
    你把Loop相关的代码都去掉,都改成handler.sendEmptyMessage(×××),然后统一在handler里面处理吧,显示Toast或者Dialog都随您便。
    但是你不应该在一个线程里先后显示几个Dialog,这样后面的Dialog直接覆盖显示在前面的Dialog上,你点击确定,前面的Dialog显示了以后,后面的才会显示。
    建议你不要用这么多Dialog和Toast,没什么意义,用Log跟踪一下流程好一点。
      

  3.   


    package package com.example.testusb;import java.nio.ByteBuffer;
    import java.util.HashMap;import android.app.Activity;
    import android.app.AlertDialog;
    import android.app.Dialog;
    import android.app.PendingIntent;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.hardware.usb.UsbDevice;
    import android.hardware.usb.UsbDeviceConnection;
    import android.hardware.usb.UsbEndpoint;
    import android.hardware.usb.UsbInterface;
    import android.hardware.usb.UsbManager;
    import android.hardware.usb.UsbRequest;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.Menu;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.Toast;
    import android.os.*;public class TestUSB extends Activity {    private Button button, button2;
        private UsbManager usbManager;
        private UsbDevice usbDevice;
        private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
        private PendingIntent pendingIntent;    Intent intent;
        StringBuffer sb = new StringBuffer();
        private TextView info;    private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                super.handleMessage(msg);
                switch (msg.what) {
                    //这里增加对case 1和2的处理
                    case 3:
    //                    createAlert("TestUSB", "33333333333333333");// ----------------------------------------这两个地方均没有显示出对话框或者toast
                        Toast.makeText(TestUSB.this, "33333333333333333", 1000).show();
                        break;
                    case 4:
    //                    createAlert("TestUSB", "44444444444444444");
                        Toast.makeText(TestUSB.this, "44444444444444444", 1000).show();
                        break;            }
            }
        };    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);        button = (Button) findViewById(R.id.button);
            usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);        pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
            IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
            registerReceiver(mUsbReceiver, filter);        button.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View arg0) {
                    new MyThread2().start();
                }
            });    }    private void createAlert(String strTitle, String strMsg) {
            Dialog alertDialog = new AlertDialog.Builder(TestUSB.this)
                    .setTitle(strTitle).setMessage(strMsg)
                    .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            // TODO Auto-generated method stub
                            setResult(RESULT_OK, intent);
                            // finish();                    }
                    }).create();        alertDialog.show();
        }    class MyThread2 extends Thread {        @Override
            public void run() {
                // TODO Auto-generated method stub
                super.run();
                Looper.prepare();
    //            Log.v("test", String.valueOf(getLineNumber(new Exception())));
    //            createAlert("Waring", "MyThread2 start");// ----------------------------------------------这个地方的对话框可以显示出来
    //            Looper.loop();
                handler.sendEmptyMessage(1);
                
                try {                HashMap<String, UsbDevice> map = usbManager.getDeviceList();
                    if (map.isEmpty()) {
    //                    Looper.prepare();
    //                    createAlert("Waring", "Empty devicelist");// ------------------------这个地方和以下所有调用createAlert的地方对话框均显示不出来
    //                    Looper.loop();
                        handler.sendEmptyMessage(2);                }
                    else
                    {
                        for (UsbDevice device : map.values()) {                        Log.e("device",
                                    "vid:" + device.getVendorId() + "   pid:" + device.getProductId()
                                            + "   " + device.getDeviceName());                        if (5334 == device.getVendorId())
                            {
                                usbDevice = device;
                            }
                            //这里也不要用Dialog
                            createAlert("Warning",
                                    "vid:" + device.getVendorId() + "   pid:" + device.getProductId()
                                            + "   " + device.getDeviceName());
                        }                    if (usbManager.hasPermission(usbDevice)) {
                            handler.sendEmptyMessage(3);//                        Looper.prepare();
    //                        Log.v("test", String.valueOf(getLineNumber(new Exception())));
    //                        createAlert("Waring", "MyThread3 start");
    //                        Looper.loop();                        new MyThread3().start();
                        } else {                        handler.sendEmptyMessage(4);//                        Looper.prepare();
    //                        Log.v("test", String.valueOf(getLineNumber(new Exception())));
    //                        createAlert("Waring", "requestPermission");
    //                        Looper.loop();                        usbManager.requestPermission(usbDevice, pendingIntent);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }    class MyThread3 extends Thread {
            @Override
            public void run() {            Looper.prepare();
                createAlert("Warning", "My thread3 receive data");
                Looper.loop();        }        private void createAlert(String strTitle, String strMsg) {
                Dialog alertDialog = new AlertDialog.Builder(TestUSB.this)
                        .setTitle(strTitle).setMessage(strMsg)
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton) {
                                setResult(RESULT_OK, intent);
                                // finish();                        }
                        }).create();            alertDialog.show();
            }        private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {            public void onReceive(Context context, Intent intent) {
                    String action = intent.getAction();
                    Log.e("action", action);
                    sb.append("action start");
                    sb.append("\n");
                    info.setText(sb);                if (ACTION_USB_PERMISSION.equals(action)) {
                        synchronized (this) {
                            usbDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                            if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                                handler.sendEmptyMessage(1);
                                if (usbDevice != null) {
                                    sb.append("BroadcastReceiver MyThread3 start");
                                    sb.append("\n");
                                    info.setText(sb);
                                    new MyThread3().start();
                                }
                            }
                            else {
                                sb.append("permission denied for device" + usbDevice.toString());
                                sb.append("\n");
                                info.setText(sb);
                                Log.d("denied", "permission denied for device " + usbDevice);
                            }
                        }
                    }
                }
            };
        }
    }帮你把代码大概的改了一下。细节需要你按上面说的来完善。
      

  4.   

    非常感谢,但是还有几个疑问。
    1.由于 MyThread3()里面调用了AlertDialog,而且出现了,那么 MyThread3()这个分支肯定被执行了。而在此之前执行了handler.sendEmptyMessage(1);我把handleMessage改为如下,但是这些toast都没有出现。
    public void handleMessage(Message msg) {
    // TODO Auto-generated method stub
    super.handleMessage(msg);
    switch (msg.what) {
    case 1:
    Toast.makeText(TestUSB.this, "111111111111", 1000).show();
    break;
    case 2:
    Toast.makeText(TestUSB.this, "22222222222", 1000).show();
    break;
    case 3:
    Toast.makeText(TestUSB.this, "33333333333333333", 1000).show();
    break;
    case 4:
    Toast.makeText(TestUSB.this, "44444444444444444", 10000).show();
    break; }
    }
    };
    2.我前面说我调用了looper.quit(),但是后面没有被执行,我能否在一个函数里面这样做,比如,这两个alert都能显示吗?
    void fun1()
    {
    Looper.prepare();
    createAlert("Warning", "111");
    Looper.loop;
    Looper.myLooper().quit();
    Looper.prepare();
    createAlert("Warning", "222");
    Looper.loop;
    Looper.myLooper().quit();}
      

  5.   

    我验证了一下,描述2中的做法是行不通的,及时前面调用了quit,后面的alert也不会显示。
      

  6.   

    同学,放弃Dialog和Toast吧,你这种情况最适合的就是用Log。
      

  7.   

    没办法打LOG,因为U口被其他设备占用,如果不用这个方法就只能用WIFI ADB
      

  8.   

    那用这么多Dialog或者Toast有什么意义呢?
      

  9.   

    可以显示调试过程中的数据啊。另外,我发现按照你的说法不是没显示,而是在一个平板上没有看到,但是在一个android*86的PC上看到了
      

  10.   

    那就弹吧,狂弹Dialog。调试完了把它们都去掉就行了。