在下面的代码中有一个名为 '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/