【问题标题】:RotationAsync with each row in List viewRotationAsync 与列表视图中的每一行
【发布时间】:2011-01-03 10:37:10
【问题描述】:

从堆栈溢出中的this 答案和那里提到的sample project,我得到了RotationAsync 的想法,其中进度条可以很好地配合设备旋转。

但是我的问题是,我有一个listview,每一行都有progress bar。有没有办法在轮换到达行时保持进度

我在 adapter 类的 getview 函数中为按钮单击侦听器创建 onclicklistener 对象。其中onClick 函数调用AsyncTask 类

由于每个getview(行)都在调用我的AsyncTask 的不同瞬间,我不能让它成为单吨类的静态。
对此有任何想法。
谢谢。

【问题讨论】:

    标签: android rotation android-asynctask


    【解决方案1】:

    所以你有一个 ListView,我假设你有一些适配器,它在它的 get 视图中托管进度条。然而,这种进步必须得到某种东西的支持,对吗?因此,只需保存该数据。就像我假设这样的适配器:

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

    然后你真的不需要 onConfigurationChanged。只需相应地读取并保存您的数据。

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

    这样当您翻转方向时,适配器将被重新创建,但它会被重新初始化为与之前相同的状态。我对您存储进度的方式和 asyncTasks 的性质做了一些假设,但我希望您可以根据需要进行调整。

    如果您不存储对任何上下文的引用,您甚至可以将整个适配器本身存储在 onRetainNonConfigurationInstance() 中并在 getLastRetainedNonConfigurationInstance() 中使用它

    【讨论】:

      【解决方案2】:


      您可以在清单文件中设置 android:configChanges="orientation" 以使您的活动在旋转时不会重新启动

      【讨论】:

      • 谢谢。仅当我只需要一种用于横向和纵向模式的布局时,它才好。检查其他答案
      【解决方案3】:


      我使用的一种解决方案 如果横向和纵向模式只有一种布局,那么我们可以通过以下方式解决这个问题 1.在manifest文件中设置activityasandroid:configChanges="orientation"
      2. 像这样覆盖onConfigurationChanged

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

      但问题仍然是,如果我需要为横向和纵向模式使用不同的布局,每行都有一个带有进度条的列表视图。我需要在使用相同 AsyncTask 类的旋转时保留进度。

      【讨论】:

        【解决方案4】:

        如何设置每个行项的百分比值?为什么不将该值更新为数据项。你可以有一些像下面这样的东西。既然你有数据项,你可以存储任何你想要的东西:)
        Ps:我想知道我可以在评论中格式化文本而不添加新的答案。

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

        【讨论】:

          猜你喜欢
          • 2011-09-29
          • 1970-01-01
          • 1970-01-01
          • 2011-11-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-08
          相关资源
          最近更新 更多