Cursor adapter
for example:
a cursor adapter need to override two method:
Bindview
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)
|
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