2016年1月6日 星期三

Cursor adapter

Cursor adapter
for example:
a cursor adapter need to override two method:
  1. Bindview

  2. newView

newView return a list of View,but no data in it,the view pass to Bindview ()


Bindview take the existing view, and than update it with the cursor of the data.


example of newView()
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
  View view = LayoutInflater.from(context).inflate(R.layout.list_item_forecast, parent, false);


  return view;
}


example of Bindview ()
public void bindView(View view, Context context, Cursor cursor) {
  // our view is pretty simple here --- just a text view
  // we'll keep the UI functional with a simple (and slow!) binding.


  // Read weather icon ID from cursor
  int weatherId = cursor.getInt(ForecastFragment.COL_WEATHER_ID);
  // Use placeholder image for now
  ImageView iconView = (ImageView) view.findViewById(R.id.list_item_icon);
  iconView.setImageResource(R.drawable.ic_launcher);


  //Read date from cursor
  Long date=cursor.getLong(ForecastFragment.COL_WEATHER_DATE);


  TextView dateview= (TextView) view.findViewById(R.id.list_item_date_textview);


  dateview.setText(Utility.getFriendlyDayString(context,date));
  // Read weather forecast from cursor
  String w_forecast=cursor.getString(ForecastFragment.COL_WEATHER_DESC);
  TextView forecastView=(TextView) view.findViewById(R.id.list_item_forecast_textview);
  forecastView.setText(w_forecast);


  // Read user preference for metric or imperial temperature units
  boolean isMetric = Utility.isMetric(context);


  // Read high temperature from cursor
  double high = cursor.getDouble(ForecastFragment.COL_WEATHER_MAX_TEMP);
  TextView highView = (TextView) view.findViewById(R.id.list_item_high_textview);
  highView.setText(Utility.formatTemperature(high, isMetric));


  //  Read low temperature from cursor
  double low = cursor.getDouble(ForecastFragment.COL_WEATHER_MIN_TEMP);
  TextView lowView = (TextView) view.findViewById(R.id.list_item_low_textview);
  lowView.setText(Utility.formatTemperature(low, isMetric));
}



until to fragment with no UI


Two Item View Types in a same itst view
like this

concept:

can use in cursor adapter and arrayadapter
the adpater first identify the index of a row, for example, if row index is 1.use layout 1,other use layout2


implement:

first ,override twomethod getViewTypeCount and getItemViewType



getViewTypeCount   return the View type number,if 2


public int getViewTypeCount() {
  return 2;
}


getItemViewType determine the type of the View


@Override
public int getItemViewType(int position) {
  return (position==0)?VIEW_TYPE_TODAY:VIEW_TYPE_FUTUREDAY;
}


here we use the position of the cursor to determine.


Returns the current position of the cursor in the row set.


Second.modified newView



example:
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
  // Choose the layout type
  int viewType = getItemViewType(cursor.getPosition());
  int layoutId = -1;


  if(viewType==VIEW_TYPE_FUTUREDAY){
      layoutId=R.layout.list_item_forecast;
  }else{
      layoutId=R.layout.list_item_forecast_today;
  }
  return LayoutInflater.from(context).inflate(layoutId, parent, false);
}


we need to add the code to change the layout we use


important!!!! if we don’t want ot change the bindview,the iteam in two  layout sholud have same id



Cursor adapter for list view
first problem, what is the different of the two constructer?

public MyCursorAdapter(Context context, Cursor c, int flags) {
       super(context, c, flags);
   }

   public MyCursorAdapter(Context context, Cursor c, boolean autoRequery) {
       super(context, c, autoRequery);
   }


public MyCursorAdapter(Context context, Cursor c, boolean autoRequery)  first

if use this and set true

If true the adapter will call requery() on the cursor whenever it changes so the most recent data is always displayed. Using true here is discouraged.

that mean,if set to true,when we add the data to the database,the list view will auto update



public MyCursorAdapter(Context context, Cursor c, int flags)
the flag can be
FLAG_AUTO_REQUERY
FLAG_REGISTER_CONTENT_OBSERVER
0

from the source code, when the autoRequeryset to true is eaual to the flags set to FLAG_AUTO_REQUERY,that mean when we set to FLAG_AUTO_REQUERY ,the
when we add the data to the database,the list view will auto update too

However!!!!!form the document,

FLAG_AUTO_REQUERY

Added in API level 11
int FLAG_AUTO_REQUERY
This constant was deprecated in API level 11.
This option is discouraged, as it results in Cursor queries being performed on the application's UI thread and thus can cause poor responsiveness or even Application Not Responding errors. As an alternative, use LoaderManager with a CursorLoader.
If set the adapter will call requery() on the cursor whenever a content change notification is delivered. Implies FLAG_REGISTER_CONTENT_OBSERVER.
Constant Value: 1 (0x00000001)
that mean we should not use MyCursorAdapter(Context context, Cursor c, FLAG_AUTO_REQUERY ) and

MyCursorAdapter(Context context, Cursor c, True)

How about FLAG_REGISTER_CONTENT_OBSERVER?

document said

FLAG_REGISTER_CONTENT_OBSERVER

Added in API level 11
int FLAG_REGISTER_CONTENT_OBSERVER
If set the adapter will register a content observer on the cursor and will call onContentChanged() when a notification comes in. Be careful when using this flag: you will need to unset the current Cursor from the adapter to avoid leaks due to its registered observers. This flag is not needed when using a CursorAdapter with a CursorLoader.
Constant Value: 2 (0x00000002)

it will call the onContentChanged method of the Cursor adapter


protected void onContentChanged() {
       if (mAutoRequery && mCursor != null && !mCursor.isClosed()) {
           if (false) Log.v("Cursor", "Auto requerying " + mCursor + " due to update");
           mDataValid = mCursor.requery();
       }
   }


when we only set the flag is FLAG_REGISTER_CONTENT_OBSERVER, the mAutoRequery will be false,so onContentChanged do nothing !!!!

we should see about the LoaderManager with CursorLoader to handle the auto update the List View