2

ハンドラーをアクティビティに登録しています。handleMessage()は、アダプターでnotifyDataSetChangedを呼び出します。アクティビティが最初に焦点を合わせている間、物事は機能します。ただし、アクティビティから移動して戻ったときに、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;
}

もう1つの情報は、ハンドラーをバインダーを通過させてからランナブルに渡すことです。これは、サービスでバックグラウンドスレッドを実行するために行います。これは問題ではないと思います。

編集: ハンドラーは、2回目にナビゲートされたときにアクティビティに関連付けられていないようです(おそらくonCreateが新しいハンドラーを作成するためです)。古いハンドラーを再関連付けまたは保持する方法はありますか?

更新 アクティビティは、別のアクティビティへのフォーカスを失うと破棄されます。

4

2 に答える 2

1

アクティビティから離れるときに、アクティビティのonDestroyメソッドにログメッセージを入れて、メッセージが破棄されているかどうかを確認します。したがって、タスクに古いアクティビティのハンドラーが含まれている可能性があります。

于 2012-04-10T18:01:18.037 に答える
0

これが私の答えです。 http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentRetainInstance.htmlに大きく依存しています

本当に彼らのコードを取り、それを変更しただけなので、スレッド(作業)を再開するたびにフラグメントを作り直さなければなりません。そして、ハンドラを介してアクティビティと通信します。

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

public class WorkFragment extends 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);

}
于 2012-04-19T20:21:16.073 に答える