2
我程序性的机器人BLE sample.I希望它刚才显示外围巫婆它已经扫描我的名单上view.Why我必须把为什么必须将代码放在“runonuithread”方法中?
mLeScanListAdpter.addDevice(device);
mLeScanListAdpter.notifyDataSetChanged();
在runOnUiThread()
方法?
如果我不使用这种方法,当我的程序发现一个设备时,列表视图将不会显示设备信息,它会在我触摸手机屏幕几秒钟后显示它。 我认为,onLeScan()
方法上主要thread.So运行,
mLeScanListAdpter.addDevice(device);
mLeScanListAdpter.notifyDataSetChanged();
运行在主线程,甚至我不把它放在runOnUiThread()
方法。并且,主要thread = UI thread
,不是吗?
所以,我认为,它运行在ui Thread上,即使我不把它放在runOnUiThread()
的方法中。但实际上,这是行不通的,我必须把它放在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;
}
}
}
谢谢你!我发现它在另一个线程上运行。 –