android - notifyDataSetChanged() 未通过 ArrayAdapter() 更新 DataGrid()

标签 android datagrid android-arrayadapter

在下面的代码中有一个名为 'stringList' 的 List '<'String'>' 类型的变量,它通过 ArrayAdapter 绑定(bind)到 GridView View 。下面的代码运行一个 for 循环,该循环创建一个字符串并将其添加到“stringList”。从 LogCat 输出中可以看出,当 OnCreate() 子例程结束并填充 GridView 时,将触发 ArrayAdapter 的 getView() 函数。我想要的是 GridView 在运行 for 循环的每次迭代时一次填充一个项目。

我的研究表明 notifyDataSetObersver() 函数是完成此任务的正确工具。尽管 notifyDataSetObersver() 在 for 循环的每次迭代中都会触发,但不清楚它是否在做任何事情,并且在 onCreate() 子例程结束后,我的 GridView 仍然会被填充。

如果有人有任何建议,我将不胜感激。

*请不要下面的代码(如注释中所示)依赖于粘贴在代码下方的两个名为“main”和“data_grid”的布局资源。

代码:

package com.arrayadapterupdate2;

import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.text.Layout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class Main extends Activity {

    LinearLayout mainLinearLayout;
    LayoutInflater inflater;
    GridArrayAdapter gridAdapter;
    GridView gridView;
    List<String> stringList;

    @Override
    public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
        stringList = new ArrayList<String>();
        inflater = LayoutInflater.from(this);
        //The Resource 'mainLinearLayout' is a Linear Layout in the set content view 'main'
        mainLinearLayout = (LinearLayout) this.findViewById(R.id.mainLinearLayout);
        //The Resource 'grid_view' is a layout containing an empty gridview
        gridView = (GridView) inflater.inflate(R.layout.grid_view,null);
        gridAdapter = new GridArrayAdapter(this, stringList, R.layout.grid_view);
        gridView.setAdapter(gridAdapter);
        System.out.println("main triggered");
        stringList.clear();
        int i;
        int j =10;
            for (i=0;i<=j-1;i=i+1){
            System.out.println("Loop: "+i);
            String string;
            String addedString = "String "+i;
            stringList.add(addedString); 
            gridAdapter.notifyDataSetChanged();
            }
         mainLinearLayout.addView(gridView);
    }


public class GridArrayAdapter extends ArrayAdapter implements OnClickListener {

    private Context context;
    private List<String> stringList;

    public GridArrayAdapter(Context context, List<String> stringList, int id) {
        super(context, id, stringList);
        this.context = context;
        this.stringList = stringList;

    }   
@Override

    public View getView(int position, View convertView, ViewGroup viewGroup) {
         System.out.println("Get View Triggered "+ position);
         String string = stringList.get(position);
         LinearLayout gridViewElement = new LinearLayout(context);
         TextView textView = new TextView(context);
         textView.setText(string);
         gridViewElement.addView(textView);
        if (convertView == null) { 
            convertView = (View)gridViewElement;
        }  
        return convertView;
    }

@Override 

public void notifyDataSetChanged(){

System.out.println("Notify Data Set Changed Triggered");
}

@Override 

public int getCount() {

    return stringList.size();
}

@Override 

public Object getItem(int position) {

    return stringList.get(position);
}

@Override 

public long getItemId(int position) {

    return position;
}

@Override

public void onClick(View arg0) {

}
}

}

LogCat 输出的一部分:

08-24 20:10:09.395: INFO/System.out(223): 主触发

08-24 20:10:09.395:INFO/System.out(223):循环:0

08-24 20:10:09.395:INFO/System.out(223):通知数据集已更改触发

08-24 20:10:09.395:INFO/System.out(223):循环:1

08-24 20:10:09.395:INFO/System.out(223):通知数据集已更改触发

08-24 20:10:09.395:INFO/System.out(223):循环:2

08-24 20:10:09.395:INFO/System.out(223):通知数据集已更改触发

08-24 20:10:09.395:INFO/System.out(223):循环:3

08-24 20:10:09.405:INFO/System.out(223):通知数据集已更改触发

08-24 20:10:09.405:INFO/System.out(223):循环:4

08-24 20:10:09.405:INFO/System.out(223):通知数据集已更改触发

08-24 20:10:09.405:INFO/System.out(223):循环:5

08-24 20:10:09.405:INFO/System.out(223):通知数据集已更改触发

08-24 20:10:09.405:INFO/System.out(223):循环:6

08-24 20:10:09.405:INFO/System.out(223):通知数据集已更改触发

08-24 20:10:09.405:INFO/System.out(223):循环:7

08-24 20:10:09.405:INFO/System.out(223):通知数据集已更改触发

08-24 20:10:09.405:INFO/System.out(223):循环:8

08-24 20:10:09.405:INFO/System.out(223):通知数据集已更改触发

08-24 20:10:09.405:INFO/System.out(223):循环:9

08-24 20:10:09.405:INFO/System.out(223):通知数据集已更改触发

08-24 20:10:09.415:INFO/System.out(223):创建结束

08-24 20:10:09.445:INFO/System.out(223):获取 View 触发 0

08-24 20:10:09.495:INFO/System.out(223):获取 View 触发 0

08-24 20:10:09.515: INFO/System.out(223): 获取 View 触发 1

08-24 20:10:09.515:INFO/System.out(223):获取 View 触发 2

08-24 20:10:09.525:INFO/System.out(223):获取 View 触发 3

08-24 20:10:09.525:INFO/System.out(223):获取 View 触发 4

08-24 20:10:09.525:INFO/System.out(223):获取 View 触发 5

08-24 20:10:09.537:INFO/System.out(223):获取 View 触发 6

08-24 20:10:09.537:INFO/System.out(223):获取 View 已触发 7

08-24 20:10:09.545:INFO/System.out(223):获取 View 触发 8

08-24 20:10:09.545:INFO/System.out(223):获取 View 触发 9

08-24 20:10:09.676: INFO/ActivityManager(51): 显示的 Activity

com.arrayadapterupdate2/.Main:972 毫秒(总共 972 毫秒)

Hey Kerubu 下面是我尝试将您的建议与 LogCat 输出的一部分一起实现。正如您从 LogCat 中看到的那样,虽然 notifyDataSetChanged() 被调用,但 getView() 既没有被 notifyDataSetChanged() 调用,也没有被 onCreate() 子例程的结论调用。

我非常感谢您的所有帮助,欢迎任何进一步的建议。

代码:
public class Main extends Activity {

    LinearLayout mainLinearLayout;
    LayoutInflater inflater;
    GridView gridView;
    List<String> stringList;
    Handler androidHandler;
    private GuiThreadMessageHandler guiThreadMsgHandler;
    private GridArrayAdapter gridAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
            System.out.println("On Create Started");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        stringList = new ArrayList<String>();
        inflater = LayoutInflater.from(this);
        //The Resource 'mainLinearLayout' is a Linear Layout in the set content view 'main'
        mainLinearLayout = (LinearLayout) this.findViewById(R.id.mainLinearLayout);
        //The Resource 'grid_view' is a layout containing an empty gridview
        gridView = (GridView) inflater.inflate(R.layout.grid_view,null);
        gridAdapter = new GridArrayAdapter(this, stringList, R.layout.grid_view);
        gridView.setAdapter(gridAdapter);
        stringList.clear();
        guiThreadMsgHandler = new GuiThreadMessageHandler();
        new GridArrayPopulator().execute();
        mainLinearLayout.addView(gridView);
        System.out.println("On Create Concluded");
    }

    private class GridArrayPopulator extends AsyncTask<Void,Void,Void>{

        @Override
        protected Void doInBackground(Void... params){
            /* Here do your loop and notify the Gui thread */
            int i;
            int j =10;
            Message msg;
            String addedString;
            for (i=0;i<=j-1;i=i+1){
                System.out.println("loop: "+i);
                addedString = "String "+i;
                stringList.add(addedString); 
                msg = Message.obtain(guiThreadMsgHandler);
                msg.sendToTarget();
        }
            return null;
  }
    }


public class GuiThreadMessageHandler extends Handler {
 public void handleMessage(Message m){
     System.out.println("Notify Data Set Changed Triggered ");
     gridAdapter.notifyDataSetChanged();
}
}

public class GridArrayAdapter extends ArrayAdapter implements OnClickListener {

    private Context context;
    private List<String> stringList;

    public GridArrayAdapter(Context context, List<String> stringList, int id) {
        super(context, id, stringList);
        this.context = context;
        this.stringList = stringList;

    }   
@Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {
         System.out.println("Get View Triggered "+ position);
         String string = stringList.get(position);
         LinearLayout gridViewElement = new LinearLayout(context);
         TextView textView = new TextView(context);
         textView.setText(string);
         gridViewElement.addView(textView);
        if (convertView == null) { 
            convertView = (View)gridViewElement;
        }  
        return convertView;
    }

@Override 
public void notifyDataSetChanged(){
System.out.println("Notify Data Set Changed Triggered");
}

@Override 
public int getCount() {
    return stringList.size();
}

@Override 
public Object getItem(int position) {
    return stringList.get(position);
}

@Override 
public long getItemId(int position) {
    return position;
}

@Override
public void onClick(View arg0) {
}
}
}

日志猫:
08-25 17:41:12.872: INFO/System.out(705): On Create Started
08-25 17:41:12.972: INFO/System.out(705): On Create Concluded
08-25 17:41:13.111: WARN/IInputConnectionWrapper(31516): showStatusIcon on inactive InputConnection
08-25 17:41:13.191: INFO/ActivityManager(1357): Displayed activity com.arrayadapterupdate2/.Main: 934 ms (total 934 ms)
08-25 17:41:13.261: DEBUG/vending(1482): [2073] LocalAssetCache.updateOnePackage(): No local info for com.arrayadapterupdate2
08-25 17:41:13.261: INFO/System.out(705): loop: 0
08-25 17:41:13.261: INFO/ActivityManager(1357): Stopping service: com.android.vending/.util.WorkService
08-25 17:41:13.321: INFO/System.out(705): Notify Data Set Changed Triggered 
08-25 17:41:13.321: INFO/System.out(705): Notify Data Set Changed Triggered
08-25 17:41:13.351: INFO/System.out(705): loop: 1
08-25 17:41:13.351: INFO/System.out(705): Notify Data Set Changed Triggered 
08-25 17:41:13.351: INFO/System.out(705): Notify Data Set Changed Triggered
08-25 17:41:13.351: INFO/System.out(705): loop: 2
08-25 17:41:13.361: INFO/System.out(705): Notify Data Set Changed Triggered 
08-25 17:41:13.361: INFO/System.out(705): Notify Data Set Changed Triggered
08-25 17:41:13.361: INFO/System.out(705): loop: 3
08-25 17:41:13.391: INFO/System.out(705): Notify Data Set Changed Triggered 
08-25 17:41:13.391: INFO/System.out(705): Notify Data Set Changed Triggered
08-25 17:41:13.391: INFO/System.out(705): loop: 4
08-25 17:41:13.391: INFO/System.out(705): Notify Data Set Changed Triggered 
08-25 17:41:13.391: INFO/System.out(705): Notify Data Set Changed Triggered
08-25 17:41:13.401: INFO/System.out(705): loop: 5
08-25 17:41:13.422: INFO/System.out(705): Notify Data Set Changed Triggered 
08-25 17:41:13.422: INFO/System.out(705): Notify Data Set Changed Triggered
08-25 17:41:13.422: INFO/System.out(705): loop: 6
08-25 17:41:13.441: INFO/System.out(705): Notify Data Set Changed Triggered 
08-25 17:41:13.441: INFO/System.out(705): Notify Data Set Changed Triggered
08-25 17:41:13.441: INFO/System.out(705): loop: 7
08-25 17:41:13.462: INFO/System.out(705): Notify Data Set Changed Triggered 
08-25 17:41:13.462: INFO/System.out(705): Notify Data Set Changed Triggered
08-25 17:41:13.462: INFO/System.out(705): loop: 8
08-25 17:41:13.462: INFO/System.out(705): Notify Data Set Changed Triggered 
08-25 17:41:13.462: INFO/System.out(705): Notify Data Set Changed Triggered
08-25 17:41:13.462: INFO/System.out(705): loop: 9
08-25 17:41:13.471: INFO/System.out(705): Notify Data Set Changed Triggered 
08-25 17:41:13.471: INFO/System.out(705): Notify Data Set Changed Triggered

最佳答案

我认为以下内容可以解释正在发生的事情:

onCreate() 在 GUI 线程中运行。您在 onCreate() 中循环,并且在循环中您将数据添加到 GridView。通过这样做,您实际上是在占用 GUI 线程,直到您完成循环。因此,Android 没有机会响应您对 notifyDataSetChanged() 的调用,即它无法“绘制”到屏幕上,因为您正在使用循环占用 GUI 线程。

作为建议,我将创建一个新线程并将您的循环放在那里,并从那里调用 notifyDataSetchanged() (尽管请检查 Android 文档,该方法可以从 GUI 以外的线程安全地调用。
为方便起见,android 有 AsyncTask类来帮助创建线程等。

编辑
我只是看了一些代码,我试图做与你类似的事情。似乎只允许从 GUI 线程调用 notifyDataSetchanged()。为了解决这个问题,我在 GUI 线程中创建了一个消息处理程序,它将调用 notifyDataSetchanged()。此消息处理程序将通过向其发送消息从其他线程得到通知。

关于android - notifyDataSetChanged() 未通过 ArrayAdapter() 更新 DataGrid(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7181876/

相关文章:

android - 您可以在 Android 上拦截 MMS SMS 消息并提取图像吗?

Android屏幕键盘自动弹出

c# - 将自定义对象绑定(bind)到 DataGrid

android - 微调器的数组适配器不能在 fragment 中工作,需要资源 ID

java - 锁定 GLSurfaceView 线程

android - sqlite数据库更新

c# - 如何将单元格集中在 WPF DataGrid 中的新行

c# - DataGridComboBoxColumn : how to set TextBinding

android - GridView 中 ArrayAdapter 的自定义过滤器

java - 如何动态添加项目到 ListView