现在的位置: 首页 > 综合 > 正文

android in practice_Managing a stateful list/Header and footer views

2018年04月13日 ⁄ 综合 ⁄ 共 9252字 ⁄ 字号 评论关闭

(1)ViewHolder pattern, which will make your list render significantly faster and hence scroll more smoothly.

(2) Adapter,  the views for our ListView are bound to the data source we’ll use a static movies file, via our Adapter.

list is backed by data coming from an adapter.

When having to maintain dynamic data that can change in reaction to view events (or any other event), you’ll have to create your own adapter implementation that performs the following tasks:
  If the data wrapped by the adapter changes, it must inform the view about these changes so it can redraw itself.
  If the user interacts with the view in a way that’s supposed to update the data, we must inform the adapter about this and make the according changes to the data source.

(3)Header and footer views

must add all header and footer views before adding any data to your list (via ListView.setAdapter);

       can’t rely on Adapter.getCount anymore

MyMovies.project

layout\acitivity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  <ImageView 
      android:src="@drawable/title"
      android:layout_width="fill_parent"
      android:layout_height="45px" 
      android:scaleType="fitXY" /> 
  <ListView 
      android:id="@android:id/list" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" /> 
</LinearLayout>

layout\movie_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="?android:attr/listPreferredItemHeight" 
    android:gravity="center_vertical">
  <CheckedTextView 
      android:id="@android:id/text1" 
      android:layout_width="0px" 
      android:layout_height="fill_parent" 
      android:layout_weight="0.9" 
      android:gravity="center_vertical" 
      android:paddingLeft="6dip" 
      android:paddingRight="6dip" 
      android:checkMark="?android:attr/listChoiceIndicatorMultiple" /> 
 </LinearLayout>

layout\list_footer.xml

<Button 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="?android:attr/listPreferredItemHeight" 
    android:gravity="center_vertical" 
    android:text="Back to top" 
    android:onClick="backToTop" /> 

 android:onClick="backToTop" :look for a public method called backToTop defined in our activity, which takes a single View object as a parameter.

store them as an array resource in our application.

After all, application code is supposed to contain logic, not data.

values\movies.xml

<?xml version="1.0" encoding="utf-8" ?> 
<resources>
 <string-array name="movies">
  <item id="1">The Shawshank Redemption (1994)</item> 
  <item>The Godfather (1972)</item> 
  <item>The Godfather, Part II (1974)</item> 
  <item>The Good, the Bad, and the Ugly (1966) (It.)</item> 
  <item>Pulp Fiction (1994)</item> 
  <item>Schindler\'s List (1993)</item> 
  <item>12 Angry Men (1957)</item> 
  <item>One Flew Over The Cuckoo\'s Nest (1975)</item> 
  <item>The Dark Knight (2009)</item> 
  <item>Star Wars: Episode V: The Empire Strikes Back (1980)</item> 
  <item>Casablanca (1942)</item> 
  <item>Star Wars (1977)</item> 
  <item>The Lord of the Rings: The Return of the King (2003)</item> 
  <item>The Seven Samurai (1954) (Jp.)</item> 
  <item>GoodFellas (1990)</item> 
  <item>Rear Window (1954)</item> 
  <item>City of God (2002, Brazil/Fr.)</item> 
  <item>Raiders of the Lost Ark (1981)</item> 
  <item>Fight Club (1999)</item> 
  <item>The Lord of the Rings: The Fellowship of the Ring (2001)</item> 
  <item>Once Upon a Time in the West (1969) (It.)</item> 
  <item>The Usual Suspects (1995)</item> 
  <item>Psycho (1960)</item> 
  <item>The Silence of the Lambs (1991)</item> 
  <item>Sunset Boulevard (1950)</item> 
  <item>The Matrix (1999)</item> 
  <item>Memento (2000)</item> 
  <item>Dr. Strangelove or: How I Learned To Stop Worrying and Love the Bomb (1964)</item> 
  <item>North By Northwest (1959)</item> 
  <item>Se7en (1995)</item> 
  <item>It\'s A Wonderful Life (1946)</item> 
  <item>The Lord of the Rings: The Two Towers (2002)</item> 
  <item>Citizen Kane (1941)</item> 
  <item>Leon, aka The Professional (1994) (Fr.)</item> 
  <item>Apocalypse Now (1979)</item> 
  <item>American Beauty (1999)</item> 
  <item>American History X (1998)</item> 
  <item>Taxi Driver (1976)</item> 
  <item>Forrest Gump (1994)</item> 
  <item>Vertigo (1958)</item> 
  <item>Lawrence of Arabia (1962)</item> 
  <item>Up (2009)</item> 
  <item>WALL-E (2008)</item> 
  <item>Inglourious Basterds (2009)</item> 
  <item>Paths of Glory (1957)</item> 
  <item>Amelie (2001) (Fr.)</item> 
  <item>Double Indemnity (1944)</item> 
  <item>Alien (1979)</item> 
  <item>M (1931) (Ger.)</item> 
  <item>Terminator 2: Judgment Day (1991)</item> 
  <item>To Kill A Mockingbird (1962)</item> 
  <item>Saving Private Ryan (1998)</item> 
  <item>A Clockwork Orange (1971)</item> 
  <item>The Shining (1980)</item> 
  <item>The Treasure of the Sierra Madre (1948)</item> 
  <item>The Departed (2006)</item> 
  <item>The Third Man (1949)</item> 
  <item>The Pianist (2002)</item> 
  <item>The Lives of Others (2006, Germ.)</item> 
  <item>Chinatown (1974)</item> 
  <item>Spirited Away (2001, Jp.)</item> 
  <item>City Lights (1931)</item> 
  <item>Aliens (1986)</item> 
  <item>Eternal Sunshine of the Spotless Mind (2004)</item> 
  <item>L.A. Confidential (1997)</item> 
  <item>Requiem for a Dream (2000)</item> 
  <item>Das Boot (1981) (Ger.)</item> 
  <item>Reservoir Dogs (1992)</item> 
  <item>The Bridge On The River Kwai (1957)</item> 
  <item>Monty Python and the Holy Grail (1974)</item> 
  <item>Pan\'s Labyrinth (2006)</item> 
  <item>Raging Bull (1980)</item> 
  <item>All About Eve (1950)</item> 
  <item>The Maltese Falcon (1941)</item> 
  <item>Slumdog Millionaire (2008)</item> 
  <item>Singin\' In The Rain (1952)</item> 
  <item>District 9 (2009)</item> 
  <item>Rashomon (1950) (Jp.)</item> 
  <item>Modern Times (1936)</item> 
  <item>Some Like It Hot (1959)</item> 
  <item>The Prestige (2006)</item> 
  <item>Rebecca (1940)</item> 
  <item>Downfall (2004, Germ)</item> 
  <item>Gran Torino (2008)</item> 
  <item>Cinema Paradiso (1988)</item> 
  <item>Amadeus (1984)</item> 
  <item>The Apartment (1960)</item> 
  <item>2001: A Space Odyssey (1968)</item> 
  <item>The Elephant Man (1980)</item> 
  <item>Life is Beautiful (1997) (It.)</item> 
  <item>Metropolis (1927) (Ger.)</item> 
  <item>The Great Dictator (1940)</item> 
  <item>Once Upon a Time in America (1984)</item> 
  <item>Back to the Future (1985)</item> 
  <item>Full Metal Jacket (1987)</item> 
  <item>The Bicycle Thief (1948, It.)</item> 
  <item>Mr. Smith Goes to Washington (1939)</item> 
  <item>The Sting (1973)</item> 
  <item>The Great Escape (1963)</item> 
  <item>Braveheart (1995)</item> 
  </string-array>
  </resources>

MovieAdapter.java

/**
 * Another perfectly valid approach would be to create a Movie model class.
 * get rid of the HashMap.
 */
//The MovieAdapter keeps track of selected movies
//Adapter separating data from its representation on the screen
public class MovieAdapter extends ArrayAdapter<String>  {
//storing movie state data
//this state is transient
private HashMap<Integer,Boolean> movieCollection=new HashMap<Integer,Boolean>();
public MovieAdapter(Context context) {
super(context,R.layout.movie_item,android.R.id.text1,context.getResources().getStringArray(R.array.movies));
// TODO Auto-generated constructor stub
}

public void toggleMovie(int position){
if(!isInCollection(position)){
movieCollection.put(position, true);
}
else{
movieCollection.put(position, false);
}
}

public boolean isInCollection(int position){
return movieCollection.get(position) == Boolean.TRUE;
}

@Override
//returns the view needed for each item.
//cache and reuse item views via convertView for performance reasons
public View getView(int position,View convertView,ViewGroup parent){
View listitem=super.getView(position, convertView, parent);
CheckedTextView checkMark=null;
//getTag(). This method allows us to associate arbitrary data with a view.
ViewHolder holder=(ViewHolder)listitem.getTag();
//if the ViewHolder is present
if(holder!=null){
//eliminate extra calls to findViewById
//cache findViewById’s result in a ViewHolder object
checkMark=holder.checkMark;
}
else{
checkMark=(CheckedTextView)listitem.findViewById(android.R.id.text1);
holder=new ViewHolder(checkMark);
listitem.setTag(holder);
}
checkMark.setChecked(isInCollection(position));
return listitem;
}

//internal class hold the CheckedTextView we need
private class ViewHolder{
protected final CheckedTextView checkMark;
public ViewHolder(CheckedTextView checkMark){
this.checkMark=checkMark;
}
/**
* The ViewHolder pattern can help make your ListView faster and more efficient, 
* and should always be considered 
* when you expect to have more than a few items in the list.
*/

}
}

MyMovies.java

/**
 * ListActivity takes care of many of the details of managing a ListView
 * getListView(),onListItemClick()
 *
 */
public class MyMovies extends ListActivity {
private MovieAdapter movieAdapter;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        ListView listview=getListView();
        //inflate this layout to receive a Button object
        Button backToTop=(Button)getLayoutInflater().inflate(R.layout.list_footer, null);
        backToTop.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(android.R.drawable.ic_menu_upload), null, null, null);
        listview.addFooterView(backToTop,null,true);
        this.movieAdapter=new MovieAdapter(this);
        listview.setAdapter(movieAdapter);//provide the data source for the items the list will handle
        listview.setItemsCanFocus(false);
        
    }

    @Override
    protected void onListItemClick(ListView l,View v,int position,long id){
    this.movieAdapter.toggleMovie(position);
    this.movieAdapter.notifyDataSetChanged();
    }
    
    public void backToTop(View view) {
        getListView().setSelection(0);
     }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}

抱歉!评论已关闭.