在下面的代码中有一个类型为List'<'String'>'的变量命名为'stringList',它通过和ArrayAdapter绑定到GridView视图。下面的代码运行一个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):On Create Endluded
08-24 20:10:09.445:INFO / System.out(223):获取视图触发0
08-24 20:10:09.495:INFO / System.out(223):获取视图触发0
08-24 20:10:09.515:INFO / System.out(223):获取视图触发1
08-24 20:10:09.515:INFO / System.out(223):获取视图触发2
08-24 20:10:09.525:INFO / System.out(223):获取视图触发3
08-24 20:10:09.525:INFO / System.out(223):获取视图触发4
08-24 20:10:09.525:INFO / System.out(223):获取视图触发5
08-24 20:10:09.537:INFO / System.out(223):获取视图触发6
08-24 20:10:09.537:INFO / System.out(223):获取视图触发7
08-24 20:10:09.545:INFO / System.out(223):获取视图触发8
08-24 20:10:09.545:INFO / System.out(223):获取视图触发9
08-24 20:10:09.676:INFO / ActivityManager(51):显示的活动
com.arrayadapterupdate2 /。主:972毫秒(总共972毫秒)
下面的嘿Kerubu是我试图暗示你的建议以及一部分LogCat输出。正如您在LogCat中看到的那样,虽然调用了notifyDataSetChanged(),但是getData()既没有被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) {
}
}
}
logcat的:
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
答案 0 :(得分:1)
我认为以下内容可以解释发生了什么:
onCreate()在GUI线程中运行。您正在循环onCreate()并在循环中将数据添加到GridView。通过这样做,你基本上会占用GUI线程,直到你完成循环。 Android因此无法响应您对notifyDataSetChanged()的调用,即它无法“绘制”到屏幕上,因为您正在使用循环来占用GUI线程。
作为一个建议,我会创建一个新线程并将你的循环放在那里,并从那里调用notifyDataSetchanged()(虽然请检查Android文档,可以从GUI以外的线程安全地调用此方法。 为了方便起见,android有AsyncTask类来帮助创建线程等。
修改强> 我刚看了一些代码,我试图做与你类似的事情。似乎只允许从GUI线程调用notifyDataSetchanged()。为了解决这个问题,我在GUI线程中创建了一个Message Handler,它将调用notifyDataSetchanged()。此消息处理程序将通过向其发送消息来通知其他线程。
答案 1 :(得分:0)
这大致是我认为你应该做的。请注意,我没有提供设置GridArray的代码,但它与您在原始帖子中引用的内容相同。
public class YourActivity extends Activity {
private GuiThreadMessageHandler guiThreadMsgHandler;
private GridArrayAdapter gridAdapter;
onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
guiThreadMsgHandler = new GuiThreadMessageHandler();
new GridArrayPopulator().execute();
}
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);
//String string;
addedString = "String "+i;
stringList.add(addedString);
msg = Message.obtain(guiThreadMsgHandler);
msg.sendToTarget()
}
}
}
public class GuiThreadMessageHandler extends Handler {
public void handleMessage(Message m){
gridAdapter.notifyDataSetChanged();
}