#android #multithreading #android-listview
#Android #многопоточность #android-listview
Вопрос:
у меня очень серьезная проблема, я прочитал весь пост о многопоточности в Android, но по-прежнему появляется ошибка famuse. но я вошел после второго запуска того же потока для exmaple «thGetDevice» из исходного кода;
надеюсь, вы сможете мне помочь .. спасибо..
Я получаю /** определение переменной*/ Флажок cbBlueTooth; Адаптер BluetoothAdapter mBluetoothAdapter; AlertDialog.Диалоговое окно Builder; ArrayAdapter mArrayAdapter; ListView MainListView; ProgressBar prProgressbar; Thread thGetDevices; Thread thClearDevices; Handler обработчик;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* Initial Handler */
handler=new Handler() {
@SuppressWarnings("unchecked")
@Override
public void handleMessage(final Message msg) {
/******************************
*
* this line cuse to the trouble
*/
BlueQuickActivity.this.runOnUiThread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
prProgressbar.incrementProgressBy(msg.arg1);
mArrayAdapter = (ArrayAdapter<String>)msg.obj;
mArrayAdapter.notifyDataSetInvalidated();
mArrayAdapter.notifyDataSetChanged();
prProgressbar.setVisibility(ProgressBar.INVISIBLE);
setListAdapter(mArrayAdapter);
}
});
}
};
/* Set Finalization true */
// System.runFinalizersOnExit(true);
setContentView(R.layout.main);
/* ListView Definition */
TextView tvHeader = new TextView(this);
MainListView = this.getListView();
MainListView.addHeaderView(tvHeader);
mArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
//mArrayAdapter.setNotifyOnChange(true);
prProgressbar = (ProgressBar)findViewById(R.id.progressBar1);
prProgressbar.setVisibility(ProgressBar.INVISIBLE);
/* Get Bluetooth driver */
cbBlueTooth = (CheckBox)findViewById(R.id.cbTurnBlueTooth);
dialog = new AlertDialog.Builder(this);
/* initializing Bluetooth adapter **/
mBluetoothAdapter= BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
/*ShowNotifMessage("Sorry..", "You Don't have Bluetooth Driver");
try {
Thread.sleep(3000);
android.os.Process.killProcess(android.os.Process.myPid());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
}
// Initial the thGetDeviceThread and thClearDevices
//initGetDevicesThread();
//initClearDevicesThread();
/*Listener for Checkbox*/
cbBlueTooth.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked amp;amp; !mBluetoothAdapter.isEnabled()) {
prProgressbar.setVisibility(ProgressBar.VISIBLE);
buttonView.setEnabled(false);
BluetoothAdapter.getDefaultAdapter().enable();
initGetDevicesThread();
buttonView.setEnabled(true);
}
else if (!isChecked amp;amp; mBluetoothAdapter.isEnabled()) {
prProgressbar.setVisibility(ProgressBar.VISIBLE);
buttonView.setEnabled(false);
BluetoothAdapter.getDefaultAdapter().disable();
initClearDevicesThread();
buttonView.setEnabled(true);
}
else
{
prProgressbar.setVisibility(ProgressBar.VISIBLE);
buttonView.setEnabled(false);
BluetoothAdapter.getDefaultAdapter().enable();
initGetDevicesThread();
buttonView.setEnabled(true);
}
}
});
}
/** Gets all paird devices and put them in the Listview */
private void initGetDevicesThread()
{
thGetDevices = new Thread(new Runnable() {
public void run() {
Message msg = handler.obtainMessage();
msg.what = 1;
msg.obj = getDeviceList();
handler.sendMessage(msg);
}
});
(thGetDevices).start();
}
/** clear all paird devices and put them in the Listview */
private void initClearDevicesThread()
{
thClearDevices = new Thread(new Runnable() {
public void run() {
Message msg = handler.obtainMessage();
msg.what = 2;
msg.obj = clearListOfDevices();
handler.sendMessage(msg);
}
});
(thClearDevices).start();
}
public ArrayAdapter<String> getDeviceList()
{
while(BluetoothAdapter.getDefaultAdapter().getState() != BluetoothAdapter.STATE_ON);
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName());
}
}
return mArrayAdapter;
}
private ArrayAdapter<String> clearListOfDevices()
{
while(BluetoothAdapter.getDefaultAdapter().getState() != BluetoothAdapter.STATE_OFF);
mArrayAdapter = new ArrayAdapter<String>(MainListView.getContext(), android.R.layout.simple_list_item_1);
return mArrayAdapter;
}
//** */
private void ShowNotifMessage(String strTitle,String strMsg)
{
dialog.setTitle(strTitle);
dialog.setMessage(strMsg);
dialog.show();
}
}
Ответ №1:
Вы не можете обновить пользовательский интерфейс из потока, отличного от пользовательского интерфейса. Для этого вы должны использовать runOnUiThread()
. Поместите свой код для обновления пользовательского интерфейса внутри runOnUiThread()
.
Activity_name.this.runOnUiThread(new Runnable() {
public void run() {
prProgressbar.incrementProgressBy(msg.arg1);
mArrayAdapter = (ArrayAdapter<String>)msg.obj;
mArrayAdapter.notifyDataSetInvalidated();
mArrayAdapter.notifyDataSetChanged();
prProgressbar.setVisibility(ProgressBar.INVISIBLE);
setListAdapter(mArrayAdapter);
}
});
Комментарии:
1. обработчик, предполагающий отправить сообщение в UIThread, запускает очередь.
2. да, но вы пытаетесь обновить пользовательский интерфейс из потока, отличного от пользовательского интерфейса, установив адаптер для List setListAdapter(mArrayAdapter); . Это можно сделать только из потока пользовательского интерфейса. Итак, для этого вам нужно поместить эту часть внутрь runOnUiThread().
3. не работает… ‘code’ BlueQuickActivity.this.runOnUiThread(new Runnable() { public void run() { // Автоматически сгенерированная заглушка метода TODO setListAdapter(mArrayAdapter); } });’code’ спасибо любым способом
4. с какой проблемой вы сталкиваетесь?
5. 11-12 14:36:07.205: E/AndroidRuntime (21408): android.view.ViewRoot$CalledFromWrongThreadException: Только исходный поток, создавший иерархию представлений, может касаться своих представлений. но только во второй раз, когда вызывается thead…
Ответ №2:
Попробуйте использовать обработчик, подобный приведенному ниже
Handler viewUpdateHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
~~~~your code~~~
break;
}
}
};
Комментарии:
1. объявите его как int msgToSend = 1;