Android 对notifyDataSetChanged()的处理程序调用未执行
我在活动中注册了一个处理程序。handleMessage()调用适配器上的notifyDataSetChanged。当活动具有初始焦点时,事情就会起作用。但是,当我离开活动并返回时,notifyDataSetChanged()不起作用 FileAdapter是一个ArrayAdapter。MergeAdapter是Commonware提供的自定义类_mergeAdapter包含_fileAdapter 活动代码:Android 对notifyDataSetChanged()的处理程序调用未执行,android,multithreading,listview,handler,adapter,Android,Multithreading,Listview,Handler,Adapter,我在活动中注册了一个处理程序。handleMessage()调用适配器上的notifyDataSetChanged。当活动具有初始焦点时,事情就会起作用。但是,当我离开活动并返回时,notifyDataSetChanged()不起作用 FileAdapter是一个ArrayAdapter。MergeAdapter是Commonware提供的自定义类_mergeAdapter包含_fileAdapter 活动代码: public void setUpDownloadHandler() { //
public void setUpDownloadHandler() {
// Define the Handler that receives messages from the thread and update the progress
_downloadHandler = new Handler() {
public void handleMessage(Message message) {
super.handleMessage(message);
String fileId = (String) message.obj;
int progress = message.arg1;
FileInfo tempFile = null;
for (FileInfo file: _files) {
if (file.getFileId().equals(fileId)) {
file.setDownloadProgress(progress);
tempFile = file;
}
}
if (tempFile != null) {
_files.remove(tempFile);
_files.add(tempFile);
}
_fileAdapter.notifyDataSetChanged();
_mergeAdapter.notifyDataSetChanged();
}
};
}
传递处理程序:
RunnableTask task = new DownloadFileRunnableImpl(application, the_workspace_url, the_file_info, the_workspace_info.getTitle(), the_internal_storage_directory,
_downloadHandler);
后台线程代码:
if(temp > previous) {
Message message = new Message();
message.arg1 = _currentProgress.intValue();
message.obj = _fileId;
_progressHandler.sendMessage(message);
previous = temp;
}
另一条信息是,我将处理程序通过一个活页夹传递给runnable。我这样做是为了在服务中运行后台线程。我认为这不是问题所在
编辑:
第二次导航到该处理程序时,它似乎与该活动没有关联(可能是因为onCreate创建了一个新的处理程序)。有没有办法重新关联或保留旧的处理程序
更新
当活动的焦点丢失到另一个活动时,该活动正在被销毁。我会尝试在活动的onDestroy方法中放置一条日志消息,以便在您离开活动时查看它是否正在被销毁。因此,您的任务可能有旧活动的处理程序。这是我的答案,我非常依赖它 实际上,我只是利用了他们的代码并对其进行了更改,这样每当我想再次启动线程(工作)时,我都必须重新生成片段。它通过处理程序与活动进行通信
public class Main extends Activity implements WorkProgressListener {
private static final String TAG = "tag";
private Handler handler;
private Button startWorkBtn;
private ProgressDialog progressDialog;
private boolean onSaveInstanceFlag = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG,"Main onCreate " + Utils.getThreadId());
setContentView(R.layout.main);
handler = new ProgressHandler();
startWorkBtn = (Button)this.findViewById(R.id.start_work_btn);
startWorkBtn.setEnabled(false);
startWorkBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick (View v) {
Log.i("tag","Main: startWorkBtn onClick ");
startWorkBtn.setEnabled(false);
FragmentManager fm = getFragmentManager();
Fragment workF = (Fragment)fm.findFragmentByTag("work");
if (null == workF) {
workF = new WorkFragment();
Log.i(TAG,"Main new WorkF" + Utils.getThreadId());
startProgressDialog(true);
startWorkBtn.setEnabled(false);
fm.beginTransaction().add(workF, "work").commit();
Log.i(TAG,"Main add(workF) " + Utils.getThreadId());
}
else {
// should never be able to get here.
}
}
});
FragmentManager fm = getFragmentManager();
Fragment loadingFragment = fm.findFragmentByTag("work");
Log.i(TAG,"Main findFragment " + Utils.getThreadId());
if (null == loadingFragment) {
this.startWorkBtn.setEnabled(true);
}
else {
// could also decide to show progress dialog based on savedInstanceState
this.startProgressDialog(true);
}
} // end onCreate
@Override
public void onRestart() {
Log.i(TAG,"Main onRestart " + Utils.getThreadId() );
super.onRestart();
this.onSaveInstanceFlag = false;
}
@Override
public void onResume () {
Log.i(TAG,"Main onResume " + Utils.getThreadId());
super.onResume();
this.onSaveInstanceFlag = false;
}
@Override
public void onSaveInstanceState (Bundle savedInstanceState) {
Log.i(TAG,"Main onSaveInstanceState "+ Utils.getThreadId());
this.onSaveInstanceFlag = true;
super.onSaveInstanceState(savedInstanceState);
if (null != this.progressDialog) {
savedInstanceState.putBoolean("progressDialog", true);
}
else {
savedInstanceState.putBoolean("progressDialog", false);
}
}
@Override
public void onStop () {
Log.i(TAG,"Main onStop " + Utils.getThreadId());
super.onStop();
}
@Override
public void onDestroy () {
Log.i(TAG,"Main onDestroy " + Utils.getThreadId());
super.onDestroy();
this.closeProgressDialog();
this.handler.removeCallbacksAndMessages(null);
}
public class ProgressHandler extends Handler {
@Override
public void handleMessage (Message msg) {
Log.i(TAG,"Main ProgressDialogHandler handleMessage");
Bundle b = msg.getData();
boolean isDone = b.getBoolean("isDone");
String tag = b.getString("tag");
if (isDone && !onSaveInstanceFlag) {
FragmentManager fm = getFragmentManager();
Fragment loader = (Fragment)fm.findFragmentByTag(tag);
fm.beginTransaction().remove(loader).commit();
closeProgressDialog();
Main.this.startWorkBtn.setEnabled(true);
}
}
}
@Override
public void sendProgress(String tag, int progress, int max) {
if ( progress == max) {
Log.i(TAG,"Main sendProgress " + Utils.getThreadId());
Message message = handler.obtainMessage();
Bundle b = new Bundle();
b.putBoolean("isDone", true);
b.putString("tag",tag);
message.setData(b);
this.handler.sendMessage(message);
}
}
private void startProgressDialog(boolean show) {
this.progressDialog = new ProgressDialog(this);
this.progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
this.progressDialog.setMessage("loading");
this.progressDialog.setCancelable(false);
this.progressDialog.show();
}
private void closeProgressDialog() {
if (null != this.progressDialog) {
progressDialog.cancel();
this.progressDialog = null;
}
}
} // end Main
公共类工作片段扩展了该片段{
private static final String TAG = "tag";
private boolean mReady = false;
private boolean mQuiting = false;
private boolean done = false;
public WorkFragment () {}
final Thread mThread = new Thread() {
@Override
public void run () {
synchronized(this) {
while (!mReady) {
Log.i(TAG,"WorkF notReady"+ Utils.getThreadId());
if (mQuiting) {
return;
}
try {
wait();
} catch (InterruptedException e) {
}
}
} // end synchronized
Log.i(TAG,"WorkF starting work "+ Utils.getThreadId());
try {
Log.i(TAG,"WorkF about to sleep"+ Utils.getThreadId());
Thread.currentThread().sleep(10000l);
Log.i(TAG,"WorkF almost finished "+ Utils.getThreadId());
done = true;
} catch (InterruptedException e1) {
e1.printStackTrace();
}
synchronized(this) {
while (!mReady) {
Log.i(TAG,"Activity notReady"+ Utils.getThreadId());
if (mQuiting) {
return;
}
try {
wait();
} catch (InterruptedException e) {
}
}
((WorkProgressListener)getActivity()).sendProgress(WorkFragment.this.getTag(), 100, 100);
} // end synchronized 2
}
};
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.i(TAG,"WorkF, onAttach: "+ Utils.getThreadId());
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG,"WorkF, onCreate: "+ Utils.getThreadId());
setRetainInstance(true);
mThread.start();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(TAG,"WorkF, onActivityCreated: "+ Utils.getThreadId());
if (done) {
((WorkProgressListener)getActivity()).sendProgress(WorkFragment.this.getTag(), 100, 100);
}
synchronized (mThread) {
mReady = true;
mThread.notify();
}
}
@Override
public void onStart()
{
super.onStart();
Log.i(TAG,"WorkF, onStart: "+ Utils.getThreadId() );
}
@Override
public void onDestroy() {
synchronized (mThread) {
mReady = false;
mQuiting = true;
mThread.notify();
}
super.onDestroy();
}
@Override
public void onDetach() {
synchronized (mThread) {
mReady = false;
mThread.notify();
}
super.onDetach();
}
public void restart() {
synchronized (mThread) {
mThread.notify();
}
}
}// end WorkFragment
public interface WorkProgressListener {
public void sendProgress (String tag, int progress, int max);
}
好的。如果处理程序被销毁了,它会不会失去与后台线程的连接,而不会更新新活动?我认为这就是正在发生的事情。但也可能是其他原因,这就是为什么我认为您应该检查日志消息的原因。或者,您可以在调试模式下运行它,并在活动的onDestroy中设置一个中断,然后查看它是否正在运行调用。我检查了,当我离开活动时,该活动没有被销毁。当我返回时,它会在onCreate()中创建一个新的处理程序。您的新活动未连接到旧的处理程序。因此,您的新活动将不会从旧任务中获取消息。将继续考虑如何解决此问题,但我希望有人会插话。可能会查看广播接收器,但您的新活动可能已创建,然后必须等待一段时间,广播方才能发送message。我以前使用广播接收器,但它们速度太慢。我了解到处理程序连接到线程。我想知道是否有方法恢复旧的处理程序并在新活动中使用它。将第二个同步工作语句从for循环更改为if语句,以便在创建新活动时线程不会一直等到无穷大。如果(null!=WorkFragment.this){if(mReady){((WorkProgressListener).getActivity()).sendProgress(..):}}}oops-rewrite“因此,如果没有创建新活动,线程不会一直等到无穷大”