mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-17 09:34:08 +01:00
rewrite list item logic. Use a single custom LinearLayout subclass
for both the loading and loaded phases, toggling its state once the data's available. Reuse it: pay attention to what's passed into getView and only allocate when there's no existing View to reuse. Stop caching Views, as that defeats Android list logic that might limit in-memory representation to the subset that's visible on-screen, instead tracking a set of rowids whose data is known to be good as a way of quickly drawing when there's a refresh.
This commit is contained in:
parent
83b1d4c364
commit
7efbd2697d
5 changed files with 420 additions and 324 deletions
xwords4/android/XWords4
res/layout
src/org/eehouse/android/xw4
|
@ -3,8 +3,9 @@
|
|||
|
||||
|
||||
<!-- top-level layout is hozontal, with an image and another layout -->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
<org.eehouse.android.xw4.GameListItem
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:longClickable="true"
|
||||
|
@ -13,6 +14,23 @@
|
|||
android:background="@android:drawable/list_selector_background"
|
||||
>
|
||||
|
||||
<TextView android:id="@+id/view_unloaded"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:gravity="center"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:text="@string/game_list_tmp"
|
||||
/>
|
||||
|
||||
<LinearLayout android:id="@+id/view_loaded"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
>
|
||||
|
||||
<ImageView android:id="@+id/msg_marker"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
|
@ -94,4 +112,5 @@
|
|||
/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</org.eehouse.android.xw4.GameListItem>
|
||||
|
|
|
@ -35,7 +35,7 @@ import android.widget.TextView;
|
|||
import java.io.FileInputStream;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap; // class is not synchronized
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
@ -46,10 +46,6 @@ import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
|
|||
import org.eehouse.android.xw4.jni.CommsAddrRec.CommsConnType;
|
||||
|
||||
public class GameListAdapter extends XWListAdapter {
|
||||
private Context m_context;
|
||||
private LayoutInflater m_factory;
|
||||
private int m_fieldID;
|
||||
private Handler m_handler;
|
||||
private static final boolean s_isFire;
|
||||
private static Random s_random;
|
||||
static {
|
||||
|
@ -59,79 +55,35 @@ public class GameListAdapter extends XWListAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
private class ViewInfo implements View.OnClickListener {
|
||||
private View m_view;
|
||||
private View m_hideable;
|
||||
private ExpiringTextView m_name;
|
||||
private boolean m_expanded, m_haveTurn, m_haveTurnLocal;
|
||||
private long m_rowid;
|
||||
private long m_lastMoveTime;
|
||||
private ImageButton m_expandButton;
|
||||
|
||||
public ViewInfo( View view, long rowid )
|
||||
{
|
||||
m_view = view;
|
||||
m_rowid = rowid;
|
||||
m_lastMoveTime = 0;
|
||||
}
|
||||
|
||||
public ViewInfo( View view, long rowid, boolean expanded,
|
||||
long lastMoveTime, boolean haveTurn,
|
||||
boolean haveTurnLocal ) {
|
||||
this( view, rowid );
|
||||
m_expanded = expanded;
|
||||
m_lastMoveTime = lastMoveTime;
|
||||
m_haveTurn = haveTurn;
|
||||
m_haveTurnLocal = haveTurnLocal;
|
||||
m_hideable = (LinearLayout)view.findViewById( R.id.hideable );
|
||||
m_name = (ExpiringTextView)m_view.findViewById( R.id.game_name );
|
||||
m_expandButton = (ImageButton)view.findViewById( R.id.expander );
|
||||
m_expandButton.setOnClickListener( this );
|
||||
showHide();
|
||||
}
|
||||
|
||||
private void showHide()
|
||||
{
|
||||
m_expandButton.setImageResource( m_expanded ?
|
||||
R.drawable.expander_ic_maximized :
|
||||
R.drawable.expander_ic_minimized);
|
||||
m_hideable.setVisibility( m_expanded? View.VISIBLE : View.GONE );
|
||||
|
||||
m_name.setBackgroundColor( android.R.color.transparent );
|
||||
m_name.setPct( m_handler, m_haveTurn && !m_expanded,
|
||||
m_haveTurnLocal, m_lastMoveTime );
|
||||
}
|
||||
|
||||
public void onClick( View view ) {
|
||||
m_expanded = !m_expanded;
|
||||
DBUtils.setExpanded( m_rowid, m_expanded );
|
||||
showHide();
|
||||
}
|
||||
}
|
||||
|
||||
private HashMap<Long,ViewInfo> m_viewsCache;
|
||||
private Context m_context;
|
||||
private LayoutInflater m_factory;
|
||||
private int m_fieldID;
|
||||
private Handler m_handler;
|
||||
private DateFormat m_df;
|
||||
private LoadItemCB m_cb;
|
||||
|
||||
// Track those rows known to be good. If a rowid is not in this
|
||||
// set, assume it must be loaded. Add rowids to this set as
|
||||
// they're loaded, and remove one when when it must be redrawn.
|
||||
private HashSet<Long> m_loadedRows;
|
||||
|
||||
public interface LoadItemCB {
|
||||
public void itemLoaded( long rowid );
|
||||
public void itemClicked( long rowid );
|
||||
}
|
||||
|
||||
private class LoadItemTask extends AsyncTask<Void, Void, Void> {
|
||||
private long m_rowid;
|
||||
private class LoadItemTask extends AsyncTask<Void, Void, GameSummary> {
|
||||
private GameListItem m_view;
|
||||
private Context m_context;
|
||||
// private int m_id;
|
||||
public LoadItemTask( Context context, long rowid/*, int id*/ )
|
||||
public LoadItemTask( Context context, GameListItem view )
|
||||
{
|
||||
DbgUtils.logf( "Creating LoadItemTask for row %d",
|
||||
view.getRowID() );
|
||||
m_context = context;
|
||||
m_rowid = rowid;
|
||||
// m_id = id;
|
||||
m_view = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground( Void... unused )
|
||||
protected GameSummary doInBackground( Void... unused )
|
||||
{
|
||||
// Without this, on the Fire only the last item in the
|
||||
// list it tappable. Likely my fault, but this seems to
|
||||
|
@ -143,18 +95,143 @@ public class GameListAdapter extends XWListAdapter {
|
|||
} catch ( Exception e ) {
|
||||
}
|
||||
}
|
||||
View layout = m_factory.inflate( R.layout.game_list_item, null );
|
||||
boolean hideTitle = false;//CommonPrefs.getHideTitleBar(m_context);
|
||||
GameSummary summary = DBUtils.getSummary( m_context, m_rowid, 1500 );
|
||||
if ( null == summary ) {
|
||||
m_rowid = -1;
|
||||
|
||||
long rowid = m_view.getRowID();
|
||||
GameSummary summary = DBUtils.getSummary( m_context, rowid, 1500 );
|
||||
return summary;
|
||||
} // doInBackground
|
||||
|
||||
@Override
|
||||
protected void onPostExecute( GameSummary summary )
|
||||
{
|
||||
setData( m_view, summary );
|
||||
setLoaded( m_view.getRowID() );
|
||||
m_view.setLoaded( true );
|
||||
|
||||
DbgUtils.logf( "LoadItemTask for row %d finished",
|
||||
m_view.getRowID() );
|
||||
}
|
||||
} // class LoadItemTask
|
||||
|
||||
public GameListAdapter( Context context, Handler handler, LoadItemCB cb,
|
||||
String fieldName ) {
|
||||
super( DBUtils.gamesList(context).length );
|
||||
m_context = context;
|
||||
m_handler = handler;
|
||||
m_cb = cb;
|
||||
m_factory = LayoutInflater.from( context );
|
||||
m_df = DateFormat.getDateTimeInstance( DateFormat.SHORT,
|
||||
DateFormat.SHORT );
|
||||
|
||||
m_loadedRows = new HashSet<Long>();
|
||||
m_fieldID = fieldToID( fieldName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return DBUtils.gamesList(m_context).length;
|
||||
}
|
||||
|
||||
// Views. A view depends on a summary, which takes time to load.
|
||||
// When one needs loading it's done via an async task.
|
||||
public View getView( int position, View convertView, ViewGroup parent )
|
||||
{
|
||||
GameListItem result;
|
||||
boolean mustLoad = false;
|
||||
if ( null == convertView ) {
|
||||
result = (GameListItem)
|
||||
m_factory.inflate( R.layout.game_list_item, null );
|
||||
result.setRowID( DBUtils.gamesList(m_context)[position] );
|
||||
mustLoad = true;
|
||||
} else {
|
||||
result = (GameListItem)convertView;
|
||||
long rowid = result.getRowID();
|
||||
if ( isDirty(rowid) || !result.isLoaded() ) {
|
||||
mustLoad = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( mustLoad ) {
|
||||
new LoadItemTask( m_context, result ).execute();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void inval( long rowid )
|
||||
{
|
||||
synchronized( m_loadedRows ) {
|
||||
m_loadedRows.remove( rowid );
|
||||
}
|
||||
}
|
||||
|
||||
private void dirtyAll()
|
||||
{
|
||||
synchronized( m_loadedRows ) {
|
||||
m_loadedRows.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isDirty( long rowid )
|
||||
{
|
||||
synchronized( m_loadedRows ) {
|
||||
return ! m_loadedRows.contains( rowid );
|
||||
}
|
||||
}
|
||||
|
||||
private void setLoaded( long rowid )
|
||||
{
|
||||
synchronized( m_loadedRows ) {
|
||||
m_loadedRows.add( rowid );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setField( String fieldName )
|
||||
{
|
||||
boolean changed = false;
|
||||
int newID = fieldToID( fieldName );
|
||||
if ( -1 == newID ) {
|
||||
if ( XWApp.DEBUG ) {
|
||||
DbgUtils.logf( "GameListAdapter.setField(): unable to match"
|
||||
+ " fieldName %s", fieldName );
|
||||
}
|
||||
} else if ( m_fieldID != newID ) {
|
||||
if ( XWApp.DEBUG ) {
|
||||
DbgUtils.logf( "setField: clearing views cache for change"
|
||||
+ " from %d to %d", m_fieldID, newID );
|
||||
}
|
||||
m_fieldID = newID;
|
||||
dirtyAll();
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
private int fieldToID( String fieldName )
|
||||
{
|
||||
int[] ids = {
|
||||
R.string.game_summary_field_empty
|
||||
,R.string.game_summary_field_language
|
||||
,R.string.game_summary_field_opponents
|
||||
,R.string.game_summary_field_state
|
||||
};
|
||||
int result = -1;
|
||||
for ( int id : ids ) {
|
||||
if ( m_context.getString( id ).equals( fieldName ) ) {
|
||||
result = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void setData( GameListItem layout, GameSummary summary )
|
||||
{
|
||||
if ( null != summary ) {
|
||||
final long rowid = layout.getRowID();
|
||||
String state = summary.summarizeState();
|
||||
|
||||
TextView view = (TextView)layout.findViewById( R.id.game_name );
|
||||
if ( hideTitle ) {
|
||||
view.setVisibility( View.GONE );
|
||||
} else {
|
||||
String value = null;
|
||||
switch ( m_fieldID ) {
|
||||
case R.string.game_summary_field_empty:
|
||||
|
@ -172,7 +249,7 @@ public class GameListAdapter extends XWListAdapter {
|
|||
break;
|
||||
}
|
||||
|
||||
String name = GameUtils.getName( m_context, m_rowid );
|
||||
String name = GameUtils.getName( m_context, rowid );
|
||||
|
||||
if ( null != value ) {
|
||||
value = m_context.getString( R.string.str_game_namef,
|
||||
|
@ -182,12 +259,11 @@ public class GameListAdapter extends XWListAdapter {
|
|||
}
|
||||
|
||||
view.setText( value );
|
||||
}
|
||||
|
||||
layout.setOnClickListener( new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick( View v ) {
|
||||
m_cb.itemClicked( m_rowid );
|
||||
m_cb.itemClicked( rowid );
|
||||
}
|
||||
} );
|
||||
|
||||
|
@ -245,123 +321,10 @@ public class GameListAdapter extends XWListAdapter {
|
|||
view.setVisibility( View.GONE );
|
||||
}
|
||||
|
||||
boolean expanded = DBUtils.getExpanded( m_context, m_rowid );
|
||||
ViewInfo vi = new ViewInfo( layout, m_rowid, expanded,
|
||||
summary.lastMoveTime, haveATurn,
|
||||
haveALocalTurn );
|
||||
if ( XWApp.DEBUG ) {
|
||||
DbgUtils.logf( "created new view for rowid %d", m_rowid );
|
||||
}
|
||||
synchronized( m_viewsCache ) {
|
||||
m_viewsCache.put( m_rowid, vi );
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} // doInBackground
|
||||
boolean expanded = DBUtils.getExpanded( m_context, rowid );
|
||||
|
||||
@Override
|
||||
protected void onPostExecute( Void unused )
|
||||
{
|
||||
// DbgUtils.logf( "onPostExecute(rowid=%d)", m_rowid );
|
||||
if ( -1 != m_rowid ) {
|
||||
m_cb.itemLoaded( m_rowid );
|
||||
layout.update( m_handler, expanded, summary.lastMoveTime,
|
||||
haveATurn, haveALocalTurn );
|
||||
}
|
||||
}
|
||||
} // class LoadItemTask
|
||||
|
||||
public GameListAdapter( Context context, Handler handler, LoadItemCB cb ) {
|
||||
super( DBUtils.gamesList(context).length );
|
||||
m_context = context;
|
||||
m_handler = handler;
|
||||
m_cb = cb;
|
||||
m_factory = LayoutInflater.from( context );
|
||||
m_df = DateFormat.getDateTimeInstance( DateFormat.SHORT,
|
||||
DateFormat.SHORT );
|
||||
|
||||
m_viewsCache = new HashMap<Long,ViewInfo>();
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return DBUtils.gamesList(m_context).length;
|
||||
}
|
||||
|
||||
public Object getItem( int position )
|
||||
{
|
||||
final long rowid = DBUtils.gamesList(m_context)[position];
|
||||
View layout;
|
||||
boolean haveLayout = false;
|
||||
synchronized( m_viewsCache ) {
|
||||
ViewInfo vi = m_viewsCache.get( rowid );
|
||||
haveLayout = null != vi;
|
||||
if ( haveLayout ) {
|
||||
layout = vi.m_view;
|
||||
} else {
|
||||
layout = m_factory.inflate( R.layout.game_list_tmp, null );
|
||||
vi = new ViewInfo( layout, rowid );
|
||||
m_viewsCache.put( rowid, vi );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !haveLayout ) {
|
||||
new LoadItemTask( m_context, rowid/*, ++m_taskCounter*/ ).execute();
|
||||
}
|
||||
|
||||
// this doesn't work. Rather, it breaks highlighting because
|
||||
// the background, if we don't set it, is a more complicated
|
||||
// object like @android:drawable/list_selector_background. I
|
||||
// tried calling getBackground(), expecting to get a Drawable
|
||||
// I could then clone and modify, but null comes back. So
|
||||
// layout must be inheriting its background from elsewhere or
|
||||
// it gets set later, during layout.
|
||||
// if ( (position%2) == 0 ) {
|
||||
// layout.setBackgroundColor( 0xFF3F3F3F );
|
||||
// }
|
||||
|
||||
return layout;
|
||||
} // getItem
|
||||
|
||||
public View getView( int position, View convertView, ViewGroup parent ) {
|
||||
return (View)getItem( position );
|
||||
}
|
||||
|
||||
public void inval( long rowid )
|
||||
{
|
||||
synchronized( m_viewsCache ) {
|
||||
m_viewsCache.remove( rowid );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setField( String fieldName )
|
||||
{
|
||||
boolean changed = false;
|
||||
int[] ids = {
|
||||
R.string.game_summary_field_empty
|
||||
,R.string.game_summary_field_language
|
||||
,R.string.game_summary_field_opponents
|
||||
,R.string.game_summary_field_state
|
||||
};
|
||||
int result = -1;
|
||||
for ( int id : ids ) {
|
||||
if ( m_context.getString( id ).equals( fieldName ) ) {
|
||||
result = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( -1 == result ) {
|
||||
if ( XWApp.DEBUG ) {
|
||||
DbgUtils.logf( "GameListAdapter.setField(): unable to match"
|
||||
+ " fieldName %s", fieldName );
|
||||
}
|
||||
} else if ( m_fieldID != result ) {
|
||||
if ( XWApp.DEBUG ) {
|
||||
DbgUtils.logf( "setField: clearing views cache for change"
|
||||
+ " from %d to %d", m_fieldID, result );
|
||||
}
|
||||
m_viewsCache.clear();
|
||||
m_fieldID = result;
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant debug install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2012 by Eric House (xwords@eehouse.org). All rights
|
||||
* reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
package org.eehouse.android.xw4;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
public class GameListItem extends LinearLayout
|
||||
implements View.OnClickListener {
|
||||
|
||||
private Context m_context;
|
||||
private boolean m_loaded;
|
||||
private long m_rowid;
|
||||
private View m_hideable;
|
||||
private ExpiringTextView m_name;
|
||||
private boolean m_expanded, m_haveTurn, m_haveTurnLocal;
|
||||
private long m_lastMoveTime;
|
||||
private ImageButton m_expandButton;
|
||||
private Handler m_handler;
|
||||
|
||||
public GameListItem( Context cx, AttributeSet as )
|
||||
{
|
||||
super( cx, as );
|
||||
m_context = cx;
|
||||
m_loaded = false;
|
||||
m_rowid = DBUtils.ROWID_NOTFOUND;
|
||||
m_lastMoveTime = 0;
|
||||
}
|
||||
|
||||
public void update( Handler handler, boolean expanded,
|
||||
long lastMoveTime, boolean haveTurn,
|
||||
boolean haveTurnLocal )
|
||||
{
|
||||
m_handler = handler;
|
||||
m_expanded = expanded;
|
||||
m_lastMoveTime = lastMoveTime;
|
||||
m_haveTurn = haveTurn;
|
||||
m_haveTurnLocal = haveTurnLocal;
|
||||
m_hideable = (LinearLayout)findViewById( R.id.hideable );
|
||||
m_name = (ExpiringTextView)findViewById( R.id.game_name );
|
||||
m_expandButton = (ImageButton)findViewById( R.id.expander );
|
||||
m_expandButton.setOnClickListener( this );
|
||||
showHide();
|
||||
}
|
||||
|
||||
public void setLoaded( boolean loaded )
|
||||
{
|
||||
if ( m_loaded != loaded ) {
|
||||
m_loaded = loaded;
|
||||
// This should be enough to invalidate
|
||||
findViewById( R.id.view_unloaded )
|
||||
.setVisibility( loaded ? View.GONE : View.VISIBLE );
|
||||
findViewById( R.id.view_loaded )
|
||||
.setVisibility( loaded ? View.VISIBLE : View.GONE );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLoaded()
|
||||
{
|
||||
return m_loaded;
|
||||
}
|
||||
|
||||
public void setRowID( long rowid )
|
||||
{
|
||||
m_rowid = rowid;
|
||||
}
|
||||
|
||||
public long getRowID()
|
||||
{
|
||||
return m_rowid;
|
||||
}
|
||||
|
||||
// View.OnClickListener interface
|
||||
public void onClick( View view ) {
|
||||
m_expanded = !m_expanded;
|
||||
DBUtils.setExpanded( m_rowid, m_expanded );
|
||||
showHide();
|
||||
}
|
||||
|
||||
private void showHide()
|
||||
{
|
||||
m_expandButton.setImageResource( m_expanded ?
|
||||
R.drawable.expander_ic_maximized :
|
||||
R.drawable.expander_ic_minimized);
|
||||
m_hideable.setVisibility( m_expanded? View.VISIBLE : View.GONE );
|
||||
|
||||
m_name.setBackgroundColor( android.R.color.transparent );
|
||||
m_name.setPct( m_handler, m_haveTurn && !m_expanded,
|
||||
m_haveTurnLocal, m_lastMoveTime );
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -282,7 +282,8 @@ public class GamesList extends XWListActivity
|
|||
}
|
||||
});
|
||||
|
||||
m_adapter = new GameListAdapter( this, new Handler(), this );
|
||||
String field = CommonPrefs.getSummaryField( this );
|
||||
m_adapter = new GameListAdapter( this, new Handler(), this, field );
|
||||
setListAdapter( m_adapter );
|
||||
|
||||
NetUtils.informOfDeaths( this );
|
||||
|
@ -391,11 +392,6 @@ public class GamesList extends XWListActivity
|
|||
}
|
||||
|
||||
// GameListAdapter.LoadItemCB interface
|
||||
public void itemLoaded( long rowid )
|
||||
{
|
||||
onContentChanged();
|
||||
}
|
||||
|
||||
public void itemClicked( long rowid )
|
||||
{
|
||||
// We need a way to let the user get back to the basic-config
|
||||
|
|
|
@ -41,8 +41,11 @@ public abstract class XWListAdapter implements ListAdapter {
|
|||
public boolean areAllItemsEnabled() { return true; }
|
||||
public boolean isEnabled( int position ) { return true; }
|
||||
public int getCount() { return m_count; }
|
||||
public Object getItem( int position ) { return null; }
|
||||
public long getItemId(int position) { return position; }
|
||||
public int getItemViewType(int position) { return 0; }
|
||||
public int getItemViewType( int position ) {
|
||||
return ListAdapter.IGNORE_ITEM_VIEW_TYPE;
|
||||
}
|
||||
public int getViewTypeCount() { return 1; }
|
||||
public boolean hasStableIds() { return true; }
|
||||
public boolean isEmpty() { return getCount() == 0; }
|
||||
|
|
Loading…
Add table
Reference in a new issue