【问题标题】:Handler call to notifyDataSetChanged() not executing处理程序调用 notifyDataSetChanged() 未执行
【发布时间】:2012-04-10 17:16:00
【问题描述】:

我在 Activity 中注册了一个处理程序。 handleMessage() 在适配器上调用 notifyDataSetChanged。当 Activity 具有初始焦点时,事情就会起作用。但是,当我离开 Activity 并返回时,notifyDataSetChanged() 不起作用。

FileAdapter 是一个 ArrayAdapter。 MergeAdapter 是 CommonsWare 的自定义类。 _mergeAdapter 包含 _fileAdapter。

活动代码:

 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;
}

另一条信息是我将处理程序通过Binder 传递,然后进入runnable。我这样做是为了在服务中运行后台线程。我认为这不是问题。

编辑: 似乎处理程序在第二次导航到时与活动没有关联(可能是因为 onCreate 创建了一个新的处理程序)。有没有办法重新关联或保留旧处理程序?

更新 当 Activity 失去对另一个 Activity 的关注时,该 Activity 将被销毁。

【问题讨论】:

    标签: android multithreading listview handler adapter


    【解决方案1】:

    当您离开您的活动时,我会尝试在您的活动的 onDestroy 方法中添加一条日志消息,以查看它是否被销毁。所以你的任务可能有来自旧活动的处理程序。

    【讨论】:

    • 好的。如果处理程序被销毁,它不会失去与后台线程的连接并且不会更新新活动吗?
    • 这就是我认为正在发生的事情。不过,它也可能是其他东西,这就是为什么我认为您应该检查日志消息的原因。或者您可以在调试模式下运行它并在 Activity 的 onDestroy 中设置一个中断,然后查看它是否被调用。
    • 我检查过,当我离开它时,Activity 没有被破坏。当我重新导航时,它会在 onCreate() 中创建一个新的处理程序。
    • 您的新活动未连接到旧处理程序。因此,您的新活动不会从旧任务中获取消息。将继续考虑如何解决这个问题,但希望有人能加入。可能会调查广播接收器,但您的新活动可能会被创建,然后必须等待一段时间,广播器才会发出消息。
    • 我以前使用广播接收器,但它们对于此目的来说太慢了。我读到处理程序附加到线程。我想知道是否有办法恢复旧处理程序并在新活动中使用它..
    【解决方案2】:

    这是我的答案,我非常依赖http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentRetainInstance.html

    真的只是拿走了他们的代码并对其进行了更改,因此每次我想再次启动线程(工作)时都必须重新制作片段。它通过处理程序与 Activity 进行通信。

    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
    

    公共类 WorkFragment 扩展 Fragment {

    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);
    
    }
    

    【讨论】:

    • 将第二个同步工作语句从 for 循环更改为 if 语句,这样如果进行了新活动,线程就不会等到无穷大。 if (null != WorkFragment.this){ if (mReady){ ((WorkProgressListener).getActivity()).sendProgress(....):}}
    • oops- rewrite "所以如果一个新的活动没有使线程不会等到无穷大"
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-03
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    • 1970-01-01
    • 2011-03-10
    • 1970-01-01
    相关资源
    最近更新 更多