【问题标题】:Keep GridView when resuming from sleep mode从睡眠模式恢复时保持 GridView
【发布时间】:2012-11-14 05:51:45
【问题描述】:

我遇到了一个相当大的 GridView 的问题。(大约 70 个孩子)如果我在 onCreate 上启动它或在按下主页按钮后恢复然后返回,则 GridView 工作正常。但是当我从睡眠模式恢复后恢复时,我的 BaseAdapter 再次启动并破坏了我在运行时对其所做的更改。如果我在重新启动后调用它,这也会使 getChildAt() 给出 NullPointerException。

我怎样才能让它像常规的 onPause(home button) 一样对 GridView 执行操作,并避免每次从睡眠模式恢复时 GridView 都被清除?

编辑: 我尝试为调用 BaseAdpter 的 Activity 类设置唤醒锁,但没有成功

2.Edit:自从我发布了这个问题以来,我一直在尝试使用 onPause 中的代码恢复 GridView:

 SparseArray<Parcelable> array = new SparseArray<Parcelable>();
    gridView.saveHierarchyState(array);
    bundle = new Bundle();
    bundle.putSparseParcelableArray("state", array);

这在 onResume 中:

 try{
    gridView.restoreHierarchyState(bundle.getSparseParcelableArray("state"));
    }
    catch(Exception e){
        //Most likely first start
        Log.i("SomeTag", "No GridView state found");
    }

    }

奇怪的是我似乎在屏幕上从一个地方跳到另一个地方,当我尝试 getChildAt() 时它仍然崩溃。睡眠模式后也无法获取。

  1. 编辑这是来自 BaseAdapter getView 的代码(注意!其中一些代码是不相关的)

public View getView (int position, View convertView, ViewGroup parent) {

mParentView = parent;


DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
int width = metrics.widthPixels;
int height = metrics.heightPixels;

    //sets the height for every individual box
int box = width/7*6/10;

ImageCell v = null;
if (convertView == null) {
    // If it's not recycled, create a new ImageCell.
    v = new ImageCell (mContext);
    v.setLayoutParams(new GridView.LayoutParams(box, box));
    v.setScaleType(ImageView.ScaleType.CENTER_CROP);
    v.setPadding(0, 0, 0, 0);


} else {
    v = (ImageCell) convertView;
}

v.mCellNumber = position;
v.mGrid = (GridView) mParentView;
v.mEmpty = true;
int id = 200;
v.setId(++id);

String map = str[position];
int pos = position;
int up = pos-10;
int down = pos+10;
int left = pos-1;
int right = pos+1;
if(up>=0){
above = str[up];
}
else{
    //Do nothing
}
if(down<70){
    under = str[down];
    }
else{
    //Do nothing
}
if(left<=-1){
   //Do nothing
}

else{
    lefte=str[left];
}
if(right>=70){
    //Do nothing
 }     
 else{
    righte=str[right];
 }
//if(left>-1|left!=9|left!=19|left!=29|left!=39|left!=49|left!=59){
   // lefte = str[left];
  //  }
 // else{
 //     Log.i("ImageCellAdapter", "Left is trying to break walls "+left);
    //Do nothing
  // }


if (map.equals("mountain")) {
    //Checks surroundings to find out witch drawable to set  
    v.setBackgroundResource(R.color.cell_empty);
     v.mEmpty = false;
     //All
     if(above=="mountain"&&under=="mountain"&&lefte=="mountain"&&righte=="mountain"){
            v.setImageResource(R.drawable.mountain_full);
        }
     //Single
     else if(above=="mountain"&&under!="mountain"&&lefte!="mountain"&&righte!="mountain"){
            v.setImageResource(R.drawable.mountain_down);
        }
     else if(above!="mountain"&&under=="mountain"&&lefte!="mountain"&&righte!="mountain"){
            v.setImageResource(R.drawable.mountain_up);
        }
     else if(above!="mountain"&&under!="mountain"&&lefte!="mountain"&&righte=="mountain"){
            v.setImageResource(R.drawable.mountain_left);
        }
     else if(above!="mountain"&&under!="mountain"&&lefte=="mountain"&&righte!="mountain"){
            v.setImageResource(R.drawable.mountain_right);
        }
     //Double
     else if(above=="mountain"&&under!="mountain"&&lefte!="mountain"&&righte=="mountain"){
            v.setImageResource(R.drawable.mountain_left_down);
        }
     else if(above!="mountain"&&under=="mountain"&&lefte!="mountain"&&righte=="mountain"){
            v.setImageResource(R.drawable.mountain_left_up);
        }
     else if(above=="mountain"&&under!="mountain"&&lefte=="mountain"&&righte!="mountain"){
            v.setImageResource(R.drawable.mountain_right_down);
        }
     else if(above!="mountain"&&under=="mountain"&&lefte=="mountain"&&righte!="mountain"){
            v.setImageResource(R.drawable.mountain_up_right);
        }
     else if(above!="mountain"&&under!="mountain"&&lefte=="mountain"&&righte=="mountain"){
            v.setImageResource(R.drawable.mountain_up_down);
        }
     else if(above=="mountain"&&under=="mountain"&&lefte!="mountain"&&righte!="mountain"){
            v.setImageResource(R.drawable.mountain_up_down);
        }
     //Triple
     else if(above!="mountain"&&under=="mountain"&&lefte=="mountain"&&righte=="mountain"){
            v.setImageResource(R.drawable.mountain_left_right_down);
        }
     else if(above=="mountain"&&under=="mountain"&&lefte=="mountain"&&righte!="mountain"){
            v.setImageResource(R.drawable.mountain_left_up_down);
        }
     else if(above=="mountain"&&under!="mountain"&&lefte=="mountain"&&righte=="mountain"){
            v.setImageResource(R.drawable.mountain_left_up_right);
        }
     else if(above=="mountain"&&under=="mountain"&&lefte!="mountain"&&righte=="mountain"){
            v.setImageResource(R.drawable.mountain_up_right_down);
        }
     //None
        else{
    v.setImageResource(R.drawable.mountain);
        }

}
else if(map=="start"){
    List<String> posOf = Arrays.asList(str);
    startPos=posOf.indexOf("start");
    v.mEmpty=false;
    v.setBackgroundResource(R.color.cell_empty);
    getDur();

     BitmapDrawable first = (BitmapDrawable)mContext.getResources().getDrawable(R.drawable.gress);
     BitmapDrawable second =(BitmapDrawable)mContext.getResources().getDrawable(R.drawable.ic_launcher);
     BitmapDrawable third = (BitmapDrawable)mContext.getResources().getDrawable(R.drawable.gress);
     BitmapDrawable fourth = (BitmapDrawable)mContext.getResources().getDrawable(R.drawable.ic_launcher);

    final AnimationDrawable ani = new AnimationDrawable();       
       ani.addFrame(first, duration);
       ani.addFrame(second, duration);
       ani.addFrame(third, duration);
       ani.addFrame(fourth, duration);
       ani.setOneShot(true);
     v.setImageDrawable(ani);        
       checkIfAnimationDone(ani); 
    v.post(new Runnable() {   
        public void run() {
               ani.start();
                }
        });
}
else if(map=="stop"){
    v.mEmpty=false;
    v.setBackgroundResource(R.color.cell_empty);
    v.setImageResource(R.drawable.ic_launcher);
    v.setTag(1);
}
else if(map=="grass"){
    v.mEmpty=false;
    v.setBackgroundResource(R.drawable.gress);


}
else{
   //    v.setBackgroundResource (R.color.drop_target_enabled);
v.setBackgroundResource (R.color.cell_empty);
}
//v.mGrid.requestDisallowInterceptTouchEvent (true);

//v.setImageResource (R.drawable.hello);

// Set up to relay events to the activity.
// The activity decides which events trigger drag operations.
// Activities like the Android Launcher require a long click to get a drag operation started.


return v;

}

并在 onCreate 中定义 GridView:

gridView= new BoxView(this);

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH){

              w.getDefaultDisplay().getSize(size);

              Measuredwidth = size.x;
              Measuredheight = size.y; 
            }else{
              Display d = w.getDefaultDisplay(); 
              Measuredwidth = d.getWidth(); 
              Measuredheight = d.getHeight(); 
            }
        int width = Measuredwidth/7*6;

    gridView.setLayoutParams(new GridView.LayoutParams(width,LayoutParams.FILL_PARENT, Gravity.CENTER_HORIZONTAL));
    gridView.setNumColumns(columns);
    gridView.setVerticalSpacing(0);
    gridView.setHorizontalSpacing(0);
    gridView.setPadding(0, 0, 0, 0);
    gridView.setId(101);
    gridView.setSelector(android.R.color.transparent);
    gridView.setAdapter (new ImageCellAdapter(this, MAP));

【问题讨论】:

  • 您不想在销毁活动时保留巨大的 GridView,因为这会导致内存不足的情况。你是如何填充视图的?
  • @tad 我必须让它这么大(我正在制作一个基于 GridView 的游戏),它必须始终可见并同时显示所有孩子。使用另一个视图会让我倒退几天。
  • 我在问:当您的活动开始时,您是如何填充视图的?来自数据库、保存文件等?
  • @tad 我用 BaseAdapter 填充它。每个孩子都有一个背景资源和一些 ImageResource。这是基于数组的。到目前为止,我没有遇到内存不足的问题。 (我使用每个只使用几个字节的可绘制对象)
  • 哦,视图的大小不是问题;它在 Activity 被销毁后保留视图,这是一个问题。在我看来,您需要阅读 Activity 生命周期并在 onPause 方法中保存游戏状态,然后在 onResume/onRestoreInstanceState 方法中填充 gridView。如果您愿意,我可以写一个更详细的真实答案。

标签: android gridview lifecycle android-gridview baseadapter


【解决方案1】:

您可以使用onSaveInstanceState (Bundle outState) 保存gridview的状态

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Parcelable state = gridView.onSaveInstanceState();
    outState.putParcelable("state", state);
}

然后在 onCreate 将适配器设置为 grdiview 后添加此代码

if (savedInstanceState != null) {
  Parcelable state = savedInstanceState.getParcelable("state");
  if (state != null) {
    gridView.onRestoreInstanceState(state);
    Log.d(this.getClass().getName(), "state restored!");                
  }
}

【讨论】:

【解决方案2】:

我在你的代码中注意到一件事:

gridView.setLayoutParams(new GridView.LayoutParams(width,LayoutParams.FILL_PARENT, Gravity.CENTER_HORIZONTAL));

即使GridViewViewGroup,您也无法访问LayoutParams。想一想,如果这可能,这意味着您可以将GridView 放在另一个GridView 中。

在继续之前解决这个问题,因为这会惹恼你。

例如,如果您希望 GridView 位于 LinearLayout 中,请尝试以下操作:

gridView.setLayoutParams(new LinearLayout.LayoutParams(width,LayoutParams.FILL_PARENT, Gravity.CENTER_HORIZONTAL));

这里是this answer的正确实现:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /*You have to implement what things from the gridView sould be "saved"*/
        GridView gridView = new GridView(this) {

            @Override
            public Parcelable onSaveInstanceState() {
                // Create the Parceable object with the things you want to save
                                Parceable stateOfGrid = ....etc
                return stateOfGrid;
            }

                        @Override
            public void onRestoreInstanceState(Parcelable state) {
                // Restore your grid's parameters that you previously implemented in onSaveInstanceState
                super.onRestoreInstanceState(state);
                                ...
            }

        };

    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onRestoreInstanceState(savedInstanceState);

                if (savedInstanceState != null) {
                    Parcelable state = savedInstanceState.getParcelable("state");
                    if (state != null) {
                        gridView.onRestoreInstanceState(state);
                        Log.d(this.getClass().getName(), "state restored!");                
                    }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // Put your grid's Parceable into the bundle
        super.onSaveInstanceState(outState);
                Parcelable state = gridView.onSaveInstanceState();
                outState.putParcelable("state", state);
    }


}

【讨论】:

  • 非常感谢!我从来没有想过。我将其替换为 RelativeLayout 而不是 LinearLayout,但我现在不在另一个内部生成 GridView。
  • 这样做的问题是,如果您获得 2 次赞成票,您将获得赏金。我现在的声誉很低,这目前没有任何区别。赏金结束后我给你 +1 :)
  • 我已经知道如何使用保存和恢复实例方法。我需要知道的是要保存什么以及之后如何恢复它。
  • +1 用于发现我不知道的错误。但答案并没有解决我的问题,因此你没有得到赏金......这次;)
【解决方案3】:

您的应用程序是否在横向模式下运行?

如果是,那么你应该考虑添加标签

"android:configChanges="keyboard|keyboardHidden|orientation" 用于 Manifest.xml 中的 Activity,这将防止 android 系统在您解锁屏幕时杀死您的 Activity 并重新启动它。

【讨论】:

  • 不好。它适用于 WebView(我之前已将此代码用于 WebView)但不适用于我的 GridView。
【解决方案4】:

尝试使用这个标签:

android:configChanges="keyboard|keyboardHidden|orientation|screenSize"

【讨论】:

  • 将屏幕尺寸添加到其他答案解决了我的问题!非常感谢您,并充分利用赏金;)
猜你喜欢
  • 1970-01-01
  • 2016-05-31
  • 1970-01-01
  • 2014-03-01
  • 1970-01-01
  • 2022-01-13
  • 1970-01-01
  • 1970-01-01
  • 2020-09-02
相关资源
最近更新 更多