为什么必须将代码放入" runonuithread"方法?

时间:2015-06-02 04:29:01

标签: android

我编写了一个Android BLE样本。我想让它显示它刚刚在我的列表视图中扫描的外围女巫。为什么我必须放

 mLeScanListAdpter.addDevice(device);
 mLeScanListAdpter.notifyDataSetChanged();
runOnUiThread()方法中

如果我不使用此方法,列表视图在我的程序发现设备时不会显示设备信息,只是在我触摸手机屏幕几秒钟后显示它。 我认为,onLeScan()方法在主线程上运行。所以,

mLeScanListAdpter.addDevice(device);
mLeScanListAdpter.notifyDataSetChanged();

在主线程上运行,即使我没有将它放在runOnUiThread()方法中。并且,主要thread = UI thread,不是吗?

所以,我认为,即使我没有将它放在runOnUiThread()方法中,也可以在ui Thread上运行。但事实上,它不起作用,我必须把它放在runOnUiThread()方法中。 我很困惑,为什么?

这是我的代码。

public class MainActivity extends ListActivity {

BluetoothManager bluetoothManager;
BluetoothAdapter bluetoothAdapter;
static final int REQUEST_ENABLE_BT = 0;
private Handler mHandler = new Handler();
LeScanListAdpter mLeScanListAdpter = new LeScanListAdpter();

BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

    @Override
    public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {

        /*------------!!!!!!!!Pay attention!!!!!!!---------------
          ------------There is the question--------------------*/
        runOnUiThread(new Runnable() {

            @Override
            public void run() {
                mLeScanListAdpter.addDevice(device);
                mLeScanListAdpter.notifyDataSetChanged();

                Log.w("scan",
                        "name:" + device.getName() + " address:"
                                + device.getAddress());
            }
        });
    }


};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setListAdapter(mLeScanListAdpter);

    // 1.获取manager
    bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
    // 2.获取adapter
    bluetoothAdapter = bluetoothManager.getAdapter();
    // 3.开启蓝牙
    /*
     * 调用isEnabled())去检测蓝牙当前是否开启。 如果该方法返回false,蓝牙被禁用。
     * 如果没有开启,将显示错误提示用户去设置开启蓝牙。
     */
    if (!bluetoothAdapter.isEnabled()) {
        Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(intent, REQUEST_ENABLE_BT);
    }
    // 4.扫描ble设备
    LeScan();

}

private void LeScan() {

    mHandler.postDelayed(new Runnable() {

        @Override
        public void run() {
            bluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }, 10000);

    bluetoothAdapter.startLeScan(mLeScanCallback);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

private class LeScanListAdpter extends BaseAdapter {

    private ArrayList<BluetoothDevice> allDevices;

    public LeScanListAdpter() {
        super();
        allDevices = new ArrayList<BluetoothDevice>();

    }

    @Override
    public int getCount() {

        return allDevices.size();
    }

    public void addDevice(BluetoothDevice d) {
        if(allDevices.contains(d)){
            return;
        }

        allDevices.add(d);
    }

    @Override
    public Object getItem(int position) {

        return allDevices.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        BluetoothDevice d = allDevices.get(position);
        // 如果view为null
        if (convertView == null) {
            convertView = MainActivity.this.getLayoutInflater().inflate(
                    R.layout.activity_main, null);

        }
        if (d.getName() == null) {
            ((TextView) convertView.findViewById(R.id.name_text_view))
                    .setText("unknown");
            ((TextView) convertView
                    .findViewById(R.id.device_address_text_view)).setText(d
                    .getAddress());
        } else {
            ((TextView) convertView.findViewById(R.id.name_text_view))
                    .setText(d.getName());
            ((TextView) convertView
                    .findViewById(R.id.device_address_text_view)).setText(d
                    .getAddress());
        }
        return convertView;
    }

   }
}

1 个答案:

答案 0 :(得分:0)

UI可以在主线程上更改,而不是仅线程&#39;主线程&#39;

也许onLeScan()方法在线程上运行,而不是主线程,

你可以检查......

if(Looper.myLooper() == Looper.getMainLooper()) {
you are on ui thread
} else {
you are not on ui thread
}