notifyDataSetChange()不通过ArrayAdapter()更新DataGrid()

时间:2011-08-24 20:29:48

标签: android datagrid android-arrayadapter

在下面的代码中有一个类型为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

2 个答案:

答案 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();

}