处理程序调用notifyDataSetChanged()不执行

时间:2012-04-10 17:16:01

标签: android multithreading listview handler adapter

我在Activity中注册了一个Handler。 handleMessage()在适配器上调用notifyDataSetChanged。在活动最初关注时,事情有效。但是,当我离开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创建了一个新的处理程序)。有没有办法重新关联或保留旧处理程序?

更新的 当活动失去对另一项活动的关注时,活动就会被破坏。

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

以下是我的回答,我非常依赖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);

}