开发者

RotationAsync with each row in List view

From this answer in stack overflow and the sample project referred there, i got the Idea of RotationAsync, where a progress bar work fine with device rotation.

But my problem is, i have a listview with each row there is progress bar. And is there any way to retain the progress while rotation for reach row.

Me creating onclicklistener object for the button click listener in getview function of my adapter class. Where its onClick function call the AsyncTask class

Since each getview (row) is calling different instant开发者_JS百科 of my AsyncTask, i cannot make it static of single ton class.

Any Idea on this.

Thanks.


So you have a ListView which I assume you have some adapter which in it's get view hosts the progress bars. However that progress must be backed by something right? So just save that data. Like I am assuming an adapter like so:

public class MyProgressBarAdapter extends BaseAdapter {
 private ArrayList<Integer> mProgessValues;
 private SparseArray<AsyncTask<?,?,?>> mTasks;
 // No stored reference to a Context

 private MyProgressBarAdapter() {

 }

 public void saveState(Bundle bundle) {
   bundle.putIntegerArrayList(getClass().getName() + ".progressValues", mProgressValues);
 }

 public Object exportLiveState() {
    return mTasks;
 }

 public static MyProgressBarAdapter restore(Bundle bundle, Object rawState) {
   MyProgressBarAdapter adapter = new MyProgressBarAdapter();
   Class<MyProgressBarAdapter> c = adapter.getClass();
   ArrayList<Integer> progresses = null;

   if (bundle != null) {
      progresses = bundle.getIntegerArrayList(c.getName() + ".progressValues");   
   }

   if (progresses == null) {
     progresses = new ArrayList<Integer>();
   }
   adapter.mProgressValues = progresses;

   if (rawState != null && rawState instanceof SparseArray) {
     adapter.mTasks = (SparseArray<AsyncTask<?,?,?>>) rawState;
   }

   return adapter;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
     convertView = getViewWithHolder(convertView, parent);
     ViewHolder holder = convertView.getTag();
     // set the appropriate things on the view elements.
     holder.position = position;
     holder.taskContainer = mTasks;
     holder.progressBar.setProgress(mProgressValues.get(position));
     convertView.setOnClickListener(new OnClickListener() {
        public void onClick(View view) {
          ViewHolder holder = view.getTag();
          int pos = holder.position;
          SparseArray<AsyncTask> tasks = holder.taskContainer;
          AsyncTask task = tasks.get(pos);
          if (task == null) {
             // Create your task
             task = new AsyncTask<?, ?, ?> (...);
             tasks.put(pos, task);
             task.execute();
          }
        }
    return convertView;
  }
  /// You can write the rest of the adapter I believe.
 ...
}

and then you don't really need onConfigurationChanged. Just read and save your data accordingly.

public class MyActivity extends Activity {

 ListView mListView;
 MyProgressBarAdapter mAdapter;

 @Override
 public void onCreate(Bundle savedState) {
   super.onCreate();
   Object[] liveState = getLastNonConfigurationInstance();

   setContentView(R.layout.mylistview_with_progressbars);
   mListView = findViewById(R.id.listview);
   // Be consistent with the index
   MyProgressBarAdapter adapter = MyProgressBarAdapter.restore(savedState, liveState[0]);
   mListView.setAdapter(adapter);
   mAdapter = adapter;
  ...
 }

 @Override
 public void onSaveInstanceState(Bundle bundle) {
   mAdapter.save(bundle);
 }

 @Override
 public Object[] onRetainNonConfigurationInstance () {
   // size to be whatever live state you need to store other than the adapter
   Object[] objects = new Object[1]; 
   // This reference will be retained between onCreate() and onDestroy() calls. 
   objects[0] = mAdapter.exportLiveState();
   // Any other things that can't be serialized
   return objects;
 }

 @Override
 public Object[] getLastNonConfigurationInstance() {
  Object[] live = (Object[]) super.getLastNonConfigurationInstance();
  if (live == null) {
    live = new Object[1];
  }
  return live;
 }

 // The rest of your activity
 ... 
}

That will make it so that when you flip the orientation, the adapter will be recreated but it will be reinitialized to the same state it was in before. I made some assumptions about the way you store your progress and the nature of your asyncTasks but I hope you can adjust as needed.

You could even, if you don't store a reference to any context, you might be able to get away with just storing the entire adapter itself inside the onRetainNonConfigurationInstance() and using that in the getLastRetainedNonConfigurationInstance()



You can set android:configChanges="orientation" in manifest file to make your activity does not restart when rotating



One solution that i used If we have only one layout for both landscape and portrait mode, then we can we can solve this by 1. Set the activity asandroid:configChanges="orientation" in manifest file
2. Override the onConfigurationChanged like this

@Override
    public void onConfigurationChanged(Configuration newConfig) {
      super.onConfigurationChanged(newConfig);

    }

But the problem is still the if i need to use different layout for both landscape and portrait mode, each have a listview with progress bar in each row. there i need to retain the progress while rotate which use same AsyncTask class.


How can you set percentage value for each row item? Why don't you update that value to the data item. You can have some thing like below. Since you have the data item you can store whatever you want :)
Ps: I wonder that I can format text in comment to not add new answer.

public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
        ViewGroup parent) 

public Object getChild(int groupPosition, int childPosition) 
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜