开发者

notifyDataSetChange() not updating DataGrid() via ArrayAdapter()

In the code below have a variable of type List '<'String'>' named 'stringList' which is bound to a GridView view via and ArrayAdapter. The code below runs a for loop which creates a string and adds it to 'stringList'. As can be seen in the LogCat output the ArrayAdapter's getView() function is triggered when the OnCreate() sub routine concludes and the GridView is populated. What I want is for the GridView to populate one item at a time as each iteration of the for loop is run.

My research indicated that notifyDataSetObersver() function is the correct tool for accomplishing this. Although notifyDataSetObersver() is triggering in each iteration of the for loop it is not clear that it's doing anything, and my GridView is still getting populated after the onCreate() sub routine concludes.

If anyone has any suggestions I would be very appreciative.

*Please not the code below (as indicated in comments) relies on a the two layout resources titled "main" and "data_grid" pasted below the code.

Code:

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) {

}
}

}

Portion of LogCat Output:

08-24 20:10:09.395: INFO/System.out(223): main triggered

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

08-24 20:10:09.395: INFO/System.out(223): Notify Data Set Changed Triggered

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

08-24 20:10:09.395: INFO/System.out(223): Notify Data Set Changed Triggered

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

08-24 20:10:09.395: INFO/System.out(223): Notify Data Set Changed Triggered

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

08-24 20:10:09.405: INFO/System.out(223): Notify Data Set Changed Triggered

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

08-24 20:10:09.405: INFO/System.out(223): Notify Data Set Changed Triggered

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

08-24 20:10:09.405: INFO/System.out(223): Notify Data Set Changed Triggered

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

08-24 20:10:09.405: INFO/System.out(223): Notify Data Set Changed Triggered

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

08-24 20:10:09.405: INFO/System.out(223): Notify Data Set Changed Triggered

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

08-24 20:10:09.405: INFO/System.out(223): Notify Data Set Changed Triggered

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

08-24 20:10:09.405: INFO/System.out(223): Notify Data Set Changed Triggered

08-24 20:10:09.415: INFO/System.out(223): On Create Concluded

08-24 20:10:09.445: INFO/System.out(223): Get View Triggered 0

08-24 20:10:09.495: INFO/System.out(223): Get View Triggered 0

08-24 20:10:09.515: INFO/System.out(223): Get View Triggered 1

08-24 20:10:09.515: INFO/System.out(223): Get View Triggered 2

08-24 20:10:09.525: INFO/System.out(223): Get View Triggered 3

08-24 20:10:09.525: INFO/System.out(223): Get View Triggered 4

08-24 20:10:09.525: INFO/System.out(223): Get View Triggered 5

08-24 20:10:09.537: INFO/System.out(223): Get View Triggered 6

08-24 20:10:09.537: INFO/System.out(223): Get View Triggered 7

08-24 20:10:09.545: INFO/System.out(223): Get View Triggered 8

08-24 20:10:09.545: INFO/System.out(223): Get View Triggered 9

08-24 20:10:09.676: INFO/ActivityManager(51): Displayed activity

com.arrayadapterupdate2/.Main: 972 ms (total 972 ms)


Hey Kerubu below is my attempt at implimenting your suggestion along with a portion of the LogCat output. As you can see from the LogCat although notifyDataSetChanged() is being called getView() is neither being called by notifyDataSetChanged() or by the conclusion of the onCreate() sub routine.

I greatly appreciate all your help, and any further advice would be welcome.

Code:

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


I think the following might explain what is happening:

onCreate() runs in the GUI thread. You're looping in onCreate() and in the loop you are adding the data to the GridView. by doing this you are essentially hogging the GUI thread until you complete your loop. Android therefore does not get chance to respond to your calls to notifyDataSetChanged() i.e. it cannot 'paint' to the screen because you are hogging the GUI thread with your loop.

As a suggestion, I would create a new thread and put your loop in there and also call notifyDataSetchanged() from there also (though please check Android docs that this method can be safely called from a thread other than the GUI. To make things easy, android has the AsyncTask class to help with thread creation etc.

Edit I just had a look at some code where I was trying to do a similar thing as you. It appears that calling notifyDataSetchanged() might only be allowed from the GUI thread. To get round this, I created a Message Handler in the GUI thread which would call notifyDataSetchanged(). This Message handler would be notified from other threads by sending it a Message.


This is roughly what I think you should do. Please note I have not included code for setting up the GridArray but it's the same as what you quoted in your original post anyway.

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

}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜