首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android GridView 實現指南:避免黑屏崩潰的關鍵錯誤與正確適配器寫法

     編輯:程式設計綜合問答

Android GridView 開發中常見「黑屏退出」問題,多因 setContentView 重複調用、適配器 getView 實現錯誤、項目布局過度嵌套導致。本文分析典型錯誤代碼,給出正確實現方案。

典型錯誤代碼分析

錯誤 1:MainActivity 重複調用 setContentView


public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);  // 第一次
    
    inflater = LayoutInflater.from(getApplicationContext());
    GridView dev_listview = (GridView) findViewById(R.id.dev_listview);
    MyAdapter gAdapter = new MyAdapter(this);
    dev_listview.setAdapter(gAdapter);
    
    setContentView(R.id.dev_listview);  // 錯誤!參數應為布局資源 ID,且重複設置導致 UI 重置
}

後果: 第二次 setContentView 參數錯誤(傳入 View ID 而非 Layout ID),導致 Activity 內容視圖丟失,黑屏/崩潰。

錯誤 2:MyAdapter getView 邏輯錯誤


public View getView(int position, View grid, ViewGroup parent) {
    inflater = (LayoutInflater) mcontext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if (grid != null) {  // 錯誤:convertView 非空時應復用,而非重新 inflate
        inflater = LayoutInflater.from(mcontext);
        grid = inflater.inflate(R.layout.item_9, parent);  // 缺少 attachToRoot=false
    }
    return grid;  // grid 可能為 null(首次調用時)
}

問題:

  • 邏輯顛倒:convertView == null 時才應 inflate
  • 缺少 ViewHolder 模式,頻繁 findViewById 導致卡頓
  • inflate 缺少第三參數 false,導致布局參數錯誤
  • 返回值可能為 null,引發 NPE

錯誤 3:item_9.xml 過度嵌套

布局嵌套 10+ 層 LinearLayout,包含大量 ImageView/TextView/ProgressBar,嚴重拖慢渲染,極易 OOM。

正確實現方案

1. MainActivity 修正


public class MainActivity extends AppCompatActivity {
    private GridView gridView;
    private MyAdapter adapter;
    private List dataList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);  // 僅調用一次
        
        gridView = findViewById(R.id.dev_listview);
        // 初始化測試數據
        for (int i = 0; i < 20; i++) {
            dataList.add(new ItemData("Item " + i, R.drawable.unpress9));
        }
        adapter = new MyAdapter(this, dataList);
        gridView.setAdapter(adapter);
    }
}

2. 高性能 MyAdapter(ViewHolder + 復用)


public class MyAdapter extends BaseAdapter {
    private Context context;
    private List dataList;
    private LayoutInflater inflater;

    public MyAdapter(Context context, List dataList) {
        this.context = context;
        this.dataList = dataList;
        this.inflater = LayoutInflater.from(context);
    }

    @Override public int getCount() { return dataList.size(); }
    @Override public Object getItem(int position) { return dataList.get(position); }
    @Override public long getItemId(int position) { return position; }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.grid_item, parent, false);  // 關鍵:false
            holder = new ViewHolder();
            holder.imageView = convertView.findViewById(R.id.item_image);
            holder.textView = convertView.findViewById(R.id.item_text);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        ItemData item = dataList.get(position);
        holder.imageView.setImageResource(item.imageRes);
        holder.textView.setText(item.title);
        return convertView;
    }

    static class ViewHolder {
        ImageView imageView;
        TextView textView;
    }
}

3. 簡潔項目布局 grid_item.xml





    

    

4. 數據模型


public class ItemData {
    public String title;
    public int imageRes;
    
    public ItemData(String title, int imageRes) {
        this.title = title;
        this.imageRes = imageRes;
    }
}

進階需求:多佈局項目(不一樣行數)

題目提到「item 有 9 行,下個 item 調用 5 行的 item5.xml,保證每行高度一致」。

方案: 使用 RecyclerView + GridLayoutManager + SpanSizeLookup,或自定義 GridView 適配器通過 getViewTypeCount() + getItemViewType() 實現多佈局,行高由最內層容器 layout_height="wrap_content" 自然撐開,配合 android:gravity="center" 對齊。

避坑清單

錯誤後果修正
重複 setContentViewUI 重置、黑屏、崩潰生命周期中僅調用一次
getView 邏輯顛倒項目不顯示、NPE、閃爍convertView==null 時 inflate,否則復用
inflate 缺少 false布局參數失效、項目尺寸異常inflater.inflate(res, parent, false)
無 ViewHolder滑動卡頓、頻繁 GC靜態內部類緩存 findViewById 結果
布局過度嵌套渲染慢、OOM、層級過深警告扁平化、使用 ConstraintLayout

總結

GridView 核心三要素:正確的 Activity 初始化、高性能適配器(ViewHolder+復用)、扁平化項目布局。新項目建議直接使用 RecyclerView + GridLayoutManager,功能更強、性能更好、API 更現代。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved