Android第四十天

跟風遠走 提交于 2019-12-04 16:18:15

1、ListView分页加载

        <1>分页的作用

                (1)避免一次性加载过多内容时,造成内存溢出;

                (2)可以增强用户体验。

        <2>实现思路

                (1)当滚动到最后一条的时候,加载新数据;

                (2)适配器的数据源要进行累加:listDatas.addAll(list)

                (3)数据发生变化时,适配器及时通知:adapter.notifyDataSetChanged()

                (4)判断是否滚到了最后一行

if (firstVisibleItem + visibleItemCount == totalItemCount ) {    
  isBottom = true; 
}

       <3>实例步骤

                (1)模拟1000条数据,以分页方式显示;

                (2)使用BaseAdapter自定义适配器显示数据;

                (3)在ListView下方增加“显示更多”按钮以实现加载下一页数据;

                (4)ListView.setOnScrollListener()方法设置滚动事件监听器;

                (5)通过滚动事件监听器判断是否滚动到最底部,若在底部则显示“显示更多“按钮;

                (6)点击“显示更多”按钮,根据当前的页码与一页显示的记录数,加载数据;

                (7)将加载的数据追加到适配器的数据源中

2、AdapterView.OnItemClickListener 列表项点击事件监听器:onItemClick(AdapterView<?> parent, View view, int position, long id)

3、OnScrollListener 滚动事件监听器

        <1>onScrollStateChanged(AbsListView view, int scrollState):监听屏幕的滚动状态的变动情况

                (1)scrollState状态说明:

                           SCROLL_STATE_TOUCH_SCROLL(1):

                            表示正在滚动。当屏幕滚动且用户使用的触碰或手指还在屏幕上时为1

                          SCROLL_STATE_FLING(2) :

                            表示手指做了抛的动作(手指离开屏幕前,用力滑了一下,屏幕产生惯性滑动)。

                          SCROLL_STATE_IDLE(0) :

                            表示屏幕已停止。屏幕停止滚动时为0。

        <2>onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount):监听屏幕滚动的item的数量

                (1)AbsListView : 当前滚动的ListView控件

                (2)firstVisibleItem:当前窗口中能看见ListView的第一个列表项ID(从0开始)   

                (3)visibleItemCount:当前窗口中能看见的ListView列表项的个数(小半个也算)   

                (4)totalItemCount:ListView列表项的总数

4、ListView的优化

        <1>ListView的高度属性设置

                (1)设置为"wrap_content"时,getView()方法一般会执行3次左右;

                (2)建议设置为"match_parent"或固定值,避免重复计算ListView的高度。

        <2>ViewHolder的使用,将findViewById()获取的控件封装起来,便于复用

        <3>convertView的复用

                (1)converView如何产生的?

                            Android中有个叫做Recycler的构件,下图是他的工作原理:

                            a、如果你有100个item,其中只有可见的项目存在内存中,其他的在Recycler中。

                            b、ListView先请求一个type1视图(getView),然后请求其他可见的item,convertView在getView中是空(null)的。

                            c、当item1滚出屏幕,并且一个新的item从屏幕底端上来时,ListView再请求一个type1视图,convertView此时不是空值了,它的值是item1。你只需设定新的数据,然后返回convertView,不必重新创建一个视图。

                (2)优点:减少getView()时通过infalter加载布局的次数,减少内存开销,提高性能

                (3)缺点:若使用异步任务下载图片时,可能会出现图片错位问题,因为convertView的位置可能是第一个

         <4>View的标签tag属性

                (1)同id属性一样,标识控件的唯一性

                (2)View.setTag(Object)设置控件的标签

                (3)View.getTag()获取控件的标签

                (4)View.setTag()+ViewHolder+convertView复用,减少布局加载和findViewBy的次数,降低的内存开销,提升性能

5、ListView实现图文混排

        <1>实现思路

                (1)创建图文混排的Item布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >


<ImageView
android:id="@+id/img"
android:layout_width="80dp"
android:layout_height="80dp"
android:scaleType="fitXY"
android:src="@drawable/ic_launcher"
/>

<TextView
android:id="@+id/tv_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/tv_phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>

                (2)根据JSON的数据结构构建实体类


package com.qf.bean;

public class Girl {
private String address;
private int age;
private String avatar;
private String name;
private String phone;

public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "Girl [address=" + address + ", age=" + age + ", avatar="
+ avatar + ", name=" + name + ", phone=" + phone + "]";
}



}

                    (3)创建BaseAdapter的子类,并实现相关方法

    
     
    package com.qf.adapter;
    
    import java.util.List;
    
    import com.qf.asy.ImgAsy;
    import com.qf.bean.Girl;
    import com.qf.day10demo02.R;
    import com.qf.util.Constant;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    public class GirlAdapter extends BaseAdapter{
    private List<Girl> data;
    private Context context;
    
    public GirlAdapter(List<Girl> data, Context context) {
    super();
    this.data = data;
    this.context = context;
    }
    
    @Override
    public int getCount() {
    return data.size();
    }
    
    @Override
    public Object getItem(int position) {
    return data.get(position);
    }
    
    @Override
    public long getItemId(int position) {
    return position;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder viewHolder = null;
    if (convertView == null) {
    viewHolder = new ViewHolder();
    
    convertView = LayoutInflater.from(context).inflate(R.layout.item, null);
    viewHolder.img = (ImageView) convertView.findViewById(R.id.img);
    viewHolder.tv_address = (TextView) convertView.findViewById(R.id.tv_address);
    viewHolder.tv_age = (TextView) convertView.findViewById(R.id.tv_age);
    viewHolder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);
    viewHolder.tv_phone = (TextView) convertView.findViewById(R.id.tv_phone);
    
    convertView.setTag(viewHolder);
    }else {
    viewHolder = (ViewHolder) convertView.getTag();
    }
    
    Girl girl = data.get(position);
    //拿到图片的后半段地址
    String avatar = girl.getAvatar();
    viewHolder.img.setTag(Constant.BASE_URL + avatar);
    //下载图片地址
    new ImgAsy(viewHolder.img).execute(Constant.BASE_URL + avatar);
    
    
    viewHolder.tv_address.setText(girl.getAddress());
    viewHolder.tv_age.setText(girl.getAge() +"");
    viewHolder.tv_name.setText(girl.getName());
    viewHolder.tv_phone.setText(girl.getPhone());
    
    return convertView;
    }
    
    class ViewHolder{
    ImageView img;
    TextView tv_address,tv_age,tv_name,tv_phone;
    
    }
    
    }

                      (4)创建网络工具类

      
       
      package com.qf.util;
      
      import java.io.ByteArrayOutputStream;
      import java.io.IOException;
      import java.io.InputStream;
      import java.net.HttpURLConnection;
      import java.net.MalformedURLException;
      import java.net.URL;
      
      
      public class NetworkUtil {
      public static byte[] getBytes(String path){
      InputStream is = null;
      ByteArrayOutputStream baos = null;
      try {
      URL url = new URL(path);
      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
      connection.setRequestMethod("GET");
      connection.setConnectTimeout(3000);
      if (200 == connection.getResponseCode()) {
      is = connection.getInputStream();
      baos = new ByteArrayOutputStream();
      int len = 0;
      byte[] buffer = new byte[1024];
      while((len = is.read(buffer)) != -1){
      baos.write(buffer,0,len);
      }
      return baos.toByteArray();
      }
      
      } catch (MalformedURLException e) {
      e.printStackTrace();
      } catch (IOException e) {
      e.printStackTrace();
      }finally{
      if (is != null) {
      try {
      is.close();
      } catch (IOException e) {
      e.printStackTrace();
      }
      }
      
      if(baos != null){
      try {
      baos.close();
      } catch (IOException e) {
      e.printStackTrace();
      }
      }
      }
      
      return null;
      
      }
      }

                        (5)创建AsyncTask的子类并实现网络请求和JSON解析的功能

        
         
        package com.qf.asy;
        
        import java.util.ArrayList;
        import java.util.List;
        
        import org.json.JSONArray;
        import org.json.JSONException;
        import org.json.JSONObject;
        
        import com.qf.bean.Girl;
        import com.qf.util.NetworkUtil;
        
        import android.content.Context;
        import android.os.AsyncTask;
        import android.widget.Toast;
        
        public class DataAsy extends AsyncTask<String, Void, List<Girl>>{
        private DataCallback callback;
        private Context context;
        
        public DataAsy(DataCallback callback, Context context) {
        super();
        this.callback = callback;
        this.context = context;
        }
        
        @Override
        protected List<Girl> doInBackground(String... params) {
        byte[] bytes = NetworkUtil.getBytes(params[0]);
        if (bytes != null) {
        String content = new String(bytes);
        //Log.i("info", "=====content===="+content);
        try {
        JSONObject object = new JSONObject(content);
        JSONArray array = object.optJSONArray("girls");
        List<Girl> girlList = new ArrayList<Girl>();
        Girl girl = null;
        //optxxx:当key值不存在的时候,程序不会崩,而是获取一个类型的默认值
        for (int i = 0; i < array.length(); i++) {
        JSONObject object2 = array.optJSONObject(i);
        girl = new Girl();
        girl.setAddress(object2.optString("address"));
        girl.setAge(object2.optInt("age"));
        girl.setAvatar(object2.optString("avatar"));
        girl.setName(object2.optString("name"));
        girl.setPhone(object2.optString("phone"));
        
        girlList.add(girl);
        
        }
        
        return girlList;
        
        } catch (JSONException e) {
        e.printStackTrace();
        }
        }
        
        return null;
        }
        
        @Override
        protected void onPostExecute(List<Girl> result) {
        super.onPostExecute(result);
        if (result == null) {
        Toast.makeText(context, "downLoad failed", Toast.LENGTH_LONG).show();
        }else {
        callback.doResult(result);
        }
        
        }
        
        
        //声明一个接口
        public interface DataCallback{
        public void doResult(List<Girl> result);
        }
        
        }

                          (6)6、将解析的数据传入到自定义BaseAdapter适配器,并显示到ListView

           
          package com.qf.day10demo02;
          
          import java.util.ArrayList;
          import java.util.List;
          
          import com.qf.adapter.GirlAdapter;
          import com.qf.asy.DataAsy;
          import com.qf.asy.DataAsy.DataCallback;
          import com.qf.bean.Girl;
          import com.qf.util.Constant;
          
          import android.app.Activity;
          import android.os.Bundle;
          import android.view.View;
          import android.view.View.OnClickListener;
          import android.widget.AbsListView;
          import android.widget.AbsListView.OnScrollListener;
          import android.widget.Button;
          import android.widget.ListView;
          
          
          public class MainActivity extends Activity
          implements OnScrollListener,OnClickListener{
          private ListView listView;
          private Button btn_more;
          private GirlAdapter adapter;
          private List<Girl> totaList = new ArrayList<Girl>();
          private int page = 0;
          
          @Override
          protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          listView = (ListView) findViewById(R.id.listView);
          btn_more = (Button) findViewById(R.id.btn_more);
          listView.setOnScrollListener(this);
          btn_more.setOnClickListener(this);
          
          getData();
          adapter = new GirlAdapter(totaList, this);//空数据源
          listView.setAdapter(adapter);
          
          
          
          
          }
          
          private void getData(){
          new DataAsy(new DataCallback() {
          @Override
          public void doResult(List<Girl> result) {
          totaList.addAll(result);
          adapter.notifyDataSetChanged();
          
          }
          },this).execute(Constant.INDEX_PATH+page);
          }
          
          @Override
          public void onScrollStateChanged(AbsListView view, int scrollState) {
          }
          @Override
          public void onScroll(AbsListView view, int firstVisibleItem,
          int visibleItemCount, int totalItemCount) {
          if (firstVisibleItem + visibleItemCount == totalItemCount) {
          btn_more.setVisibility(View.VISIBLE);
          }else {
          btn_more.setVisibility(View.GONE);
          }
          
          }
          
          @Override
          public void onClick(View v) {
          page++;
          getData();
          
          }
          
          
          }

                    <2>需要的核心类

                            (1)BaseAdapter

                            (2)AsyncTask

                            (4)HttpClient

                            (5)JSONObject/JSONArray

            6、listview其他方法

                    <1>listView.addHeaderView(view);

            
            View headView = LayoutInflater.from(this).inflate(R.layout.headlayout, null);
            //添加一个头部布局/控件,要在绑定适配器之前。
            listView.addHeaderView(headView);

                      <2>listView.addFooterView(button);

              
              Button button = new Button(this);
              button.setText("底部按钮");
              //添加一个底部布局/控件
              listView.addFooterView(button);

                        <3>listView.setEmptyView(emptyView);

                 
                TextView emptyView = (TextView) findViewById(R.id.emptyView);
                //使用前提:emptyView必须是预先存在当前布局里面,隐藏的
                listView.setEmptyView(emptyView);
                  易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
                  该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!