前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面向holder编程、自动轮询

面向holder编程、自动轮询

作者头像
六月的雨
发布2022-01-17 20:08:44
4710
发布2022-01-17 20:08:44
举报
文章被收录于专栏:Android开发指南

没有看过上一篇文章的话,建议先去阅读GooglePlay:9.代码抽取(adapter)

项目框架的搭建:

以后每个view都是holder

BaseHolder

代码语言:javascript
复制
 public abstract class BaseHolder<Data>  {//写data和t一样
    private View contentView;
    private Data data;
    protected BitmapUtils bitmapUtils;
    public BaseHolder(){
        bitmapUtils = BitmapHelper.getBitmapUtils();
        contentView=initView();
        contentView.setTag(this);
    }
    /** 创建界面*/
    public  abstract View initView();
    public View getContentView() {
        return contentView;
    }
    public void setData(Data data){
        this.data=data;
        refreshView(data);
    }
    /** 根据数据刷新界面*/
    public abstract void refreshView(Data data);
}

MoreHolder

代码语言:javascript
复制
public class MoreHolder extends BaseHolder<Integer> {
    public static final int HAS_NO_MORE=0;  // 没有额外数据了
    public static final int LOAD_ERROR=1;// 加载失败
    public static final int HAS_MORE=2;//  有额外数据
     
    private RelativeLayout rl_more_loading,rl_more_error;
     
    /**当Holder显示的时候 显示什么样子*/
    @Override
    public View initView() {
        View view=UiUtils.inflate(R.layout.load_more);
        rl_more_loading=(RelativeLayout) view.findViewById(R.id.rl_more_loading);
        rl_more_error=(RelativeLayout) view.findViewById(R.id.rl_more_error);
        return view;
    }
    private DefaultAdapter adapter;
     
    public MoreHolder(DefaultAdapter adapter) {
        super();
        this.adapter=adapter;
         
    }
    @Override
    public View getContentView() {
        loadMore();
         
        return super.getContentView();
    }
    private void loadMore() {
        // 请求服务器   加载下一批数据
        //  交给Adapter  让Adapter  加载更多数据
        adapter.loadMore();
    }
    /**根据数据做界面的修改*/
    @Override
    public void refreshView(Integer data) {
        rl_more_error.setVisibility(data==LOAD_ERROR?View.VISIBLE:View.GONE);
        rl_more_loading.setVisibility(data==HAS_MORE?View.VISIBLE:View.GONE);
         
    }
}

DefaultAdapter : 多种不同类型条目的ListView

代码语言:javascript
复制
public abstract class DefaultAdapter<Data> extends BaseAdapter {
    protected List<Data> datas;
    private static final int DEFAULT_ITEM = 0;
    private static final int MORE_ITEM = 1;
    public List<Data> getDatas() {
        return datas;
    }
    public void setDatas(List<Data> datas) {
        this.datas = datas;
    }
    public DefaultAdapter(List<Data> datas) {
        this.datas = datas;
    }
    @Override
    public int getCount() {
        return datas.size() + 1; // 最后的一个条目 就是加载更多的条目
    }
    @Override
    public Object getItem(int position) {
        return datas.get(position);
    }
    /** 根据位置 判断当前条目是什么类型 */
    @Override
    public int getItemViewType(int position) {  //20    
        if (position == datas.size()) { // 当前是最后一个条目
            return MORE_ITEM;
        }
        return getInnerItemViewType(position); // 如果不是最后一个条目 返回默认类型
    }
    private int getInnerItemViewType(int position) {
        return DEFAULT_ITEM;
    }
    /** 当前ListView 有几种不同的条目类型 */
    @Override
    public int getViewTypeCount() {
        return super.getViewTypeCount() + 1; // 2 有两种不同的类型
    }
    @Override
    public long getItemId(int position) {
        return position;
    }
    public View getView(int position, View convertView, ViewGroup parent) {
        BaseHolder holder = null;
        switch (getItemViewType(position)) {  // 判断当前条目时什么类型
        case MORE_ITEM:
            if(convertView==null){
                holder=getMoreHolder();
            }else{
                holder=(BaseHolder) convertView.getTag();
            }
            break;
        case DEFAULT_ITEM:
            if (convertView == null) {
                holder = getHolder();
            } else {
                holder = (BaseHolder) convertView.getTag();
            }
            if (position < datas.size()) {
                holder.setData(datas.get(position));
            }
            break;
        }
        return holder.getContentView();  //  如果当前Holder 恰好是MoreHolder  证明MoreHOlder已经显示
    }
    private MoreHolder holder;
    private BaseHolder getMoreHolder() {
        if(holder!=null){
            return holder;
        }else{
            holder=new MoreHolder(this);
            return holder;
        }
    }
    protected abstract BaseHolder<Data> getHolder();
     
    /**
     * 当加载更多条目显示的时候 调用该方法
     */
    public void loadMore() {
        ThreadManager.getInstance().createLongPool().execute(new Runnable() {
             
            @Override
            public void run() {
                // 在子线程中加载更多
                final List<Data> newData = onload();
                UiUtils.runOnUiThread(new Runnable() {
                     
                    @Override
                    public void run() {
                        if(newData==null){
                            holder.setData(MoreHolder.LOAD_ERROR);// 
                        }else if(newData.size()==0){
                            holder.setData(MoreHolder.HAS_NO_MORE);
                        }else{
                            // 成功了
                            holder.setData(MoreHolder.HAS_MORE);
                            datas.addAll(newData);//  给listView之前的集合添加一个新的集合
                            notifyDataSetChanged();// 刷新界面
                         
                        }
                         
                    }
                });
             
                 
            }
        });
    }
    /**
     * 加载更多数据
     */
    protected  abstract List<Data> onload();
}

修改8的代码SubjectFragment

代码语言:javascript
复制
public class SubjectFragment extends BaseFragment {
    private List<SubjectInfo> datas;
    @Override
    public View createSuccessView() {
        BaseListView  listView=new BaseListView  (UiUtils.getContext());
        listView.setAdapter(new SubjectAdapter(datas));
        return listView;
    }
    private class SubjectAdapter extends DefaultAdapter<SubjectInfo>{
        public SubjectAdapter(List<SubjectInfo> datas) {
            super(datas);
        }
        @Override
        protected BaseHolder<SubjectInfo> getHolder() {
            return new SubjectHolder();
        }
        @Override
        protected List<SubjectInfo> onload() {
            SubjectProtocol protocol=new SubjectProtocol();
            List<SubjectInfo> load = protocol.load(0);
            datas.addAll(load);
            return load;
        }
    }
    class SubjectHolder extends BaseHolder<SubjectInfo>{
        ImageView item_icon;
        TextView item_txt;
        @Override
        public View initView() {
            View contentView=UiUtils.inflate(R.layout.item_subject);
            this.item_icon=(ImageView) contentView.findViewById(R.id.item_icon);
            this.item_txt=(TextView) contentView.findViewById(R.id.item_txt);
            return contentView;
        }
        @Override
        public void refreshView(SubjectInfo data) {
            this.item_txt.setText(data.getDes());
            bitmapUtils.display(this.item_icon, HttpHelper.URL+"image?name="+data.getUrl());
        }
    }
    @Override
    protected LoadResult load() {
        SubjectProtocol protocol=new SubjectProtocol();
        datas = protocol.load(0);
        return checkData(datas);
    }
}

都是首页、APP、游戏页面很相似,所有又可以抽取

ListBaseHolder

代码语言:javascript
复制
public class ListBaseHolder extends BaseHolder<AppInfo> {
	ImageView item_icon;
	TextView item_title,item_size,item_bottom;
	RatingBar item_rating;
	
	public void refreshView(AppInfo data){
		this.item_title.setText(data.getName());// 设置应用程序的名字
		String size=Formatter.formatFileSize(UiUtils.getContext(), data.getSize());
		this.item_size.setText(size);
		this.item_bottom.setText(data.getDes());
		float stars = data.getStars();
		this.item_rating.setRating(stars); // 设置ratingBar的值
		String iconUrl = data.getIconUrl();  //http://127.0.0.1:8090/image?name=app/com.youyuan.yyhl/icon.jpg
		
		// 显示图片的控件
		bitmapUtils.display(this.item_icon, HttpHelper.URL+"image?name="+iconUrl);
	}
	@Override
	public View initView() {
		View contentView=View.inflate(UiUtils.getContext(), R.layout.item_app, null);
		this.item_icon=(ImageView) contentView.findViewById(R.id.item_icon);
		this.item_title=(TextView) contentView.findViewById(R.id.item_title);
		this.item_size=(TextView) contentView.findViewById(R.id.item_size);
		this.item_bottom=(TextView) contentView.findViewById(R.id.item_bottom);
		this.item_rating=(RatingBar) contentView.findViewById(R.id.item_rating);
		return contentView;
	}
}

ListBaseAdapter

代码语言:javascript
复制
public abstract class ListBaseAdapter extends DefaultAdapter<AppInfo> {
    public ListBaseAdapter(List<AppInfo> datas) {
        super(datas);
    }
    @Override
    protected BaseHolder<AppInfo> getHolder() {
        return new ListBaseHolder();
    }
    @Override
    protected abstract List<AppInfo> onload();
     
}

GameFragment

代码语言:javascript
复制
public class GameFragment extends BaseFragment {
	private List<AppInfo> datas;
	/**
	 * 加载成功的界面
	 */
	@Override
	public View createSuccessView() {
		BaseListView  listView=new BaseListView(UiUtils.getContext());
		listView.setAdapter(new ListBaseAdapter(datas){
			@Override
			protected List<AppInfo> onload() {
				GameProtocol protocol=new GameProtocol();
				List<AppInfo> load = protocol.load(datas.size());  //  
				datas.addAll(load);
				return load;
			}
			
		});
		return listView;
	}
	/**
	 * 请求服务器加载数据
	 */
	@Override
	protected LoadResult load() {
		GameProtocol protocol=new GameProtocol();
		datas = protocol.load(0);
		return checkData(datas);
	}
}

AppFragment

代码语言:javascript
复制
public class AppFragment extends BaseFragment {
	private List<AppInfo> datas;
	/**
	 * 当加载成功的时候 显示的界面
	 */
	@Override
	public View createSuccessView() {
		BaseListView  listView=new BaseListView(UiUtils.getContext());
		listView.setAdapter(new ListBaseAdapter(datas){
			@Override
			protected List<AppInfo> onload() {
				AppProtocol protocol=new AppProtocol();
				List<AppInfo> load = protocol.load(0);
				datas.addAll(load);
				return load;
			}
			
		});
		return listView;
	}
	/**
	 * 请求服务器 获取服务器的数据
	 */
	protected LoadResult load() {
		AppProtocol protocol=new AppProtocol();
		datas = protocol.load(0);
		return checkData(datas); // 检查数据 有三种结果  成功, 错误,空
	}
}

首页有个几张图片的展示栏,所以又是一个holder

HomePictureHolder (自动轮询)

代码语言:javascript
复制
public class HomePictureHolder extends BaseHolder<List<String>> {
	/* 当new HomePictureHolder()就会调用该方法 */
	private ViewPager viewPager;
	private List<String> datas;
	@Override
	public View initView() {
		viewPager = new ViewPager(UiUtils.getContext());
		viewPager.setLayoutParams(new AbsListView.LayoutParams(
				LayoutParams.MATCH_PARENT, UiUtils
						.getDimens(R.dimen.home_picture_height)));//转换成dp
		return viewPager;
	}
	/* 当 holder.setData 才会调用 */
	@Override
	public void refreshView(List<String> datas) {
		this.datas = datas;
		viewPager.setAdapter(new HomeAdapter());
		viewPager.setCurrentItem(2000*datas.size());// 设置起始的位置   Integer.Max_Vlue/2,这样开始位置也能向后划了
		viewPager.setOnTouchListener(new OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					runTask.stop();   
					break;
// 事件的取消,有可能按下viewpager滑动到listview上停止就不轮播了
				case MotionEvent.ACTION_CANCEL:  
				case MotionEvent.ACTION_UP:
					runTask.start();
					break;
				}
				
				return false; // viewPager 触摸事件 返回值要是false  
			}
		});
		runTask = new AuToRunTask();
		runTask.start();
	}
	boolean flag;
	private AuToRunTask runTask;
//Runnable并不是开启子线程,所以可以在主线程运行,thread才是开启线程
	public class AuToRunTask implements Runnable{
		@Override
		public void run() {
			if(flag){
				UiUtils.cancel(this);  // 取消之前
				int currentItem = viewPager.getCurrentItem();
				currentItem++;
				viewPager.setCurrentItem(currentItem);
				//  延迟执行当前的任务
				UiUtils.postDelayed(this, 2000);// 递归调用
			}
		}
		public void start(){
			if(!flag){
				UiUtils.cancel(this);  // 取消之前
				flag=true;
				UiUtils.postDelayed(this, 2000);// 递归调用
			}
		}
		public  void stop(){
			if(flag){
				flag=false;
				UiUtils.cancel(this);
			}
		}
		
	}
	
	class HomeAdapter extends PagerAdapter {
		// 当前viewPager里面有多少个条目
		LinkedList<ImageView> convertView=new LinkedList<ImageView>();
		// ArrayList
		@Override
		public int getCount() {
			return	Integer.MAX_VALUE;//这样写条目就能一直划了
		}
		/* 判断返回的对象和 加载view对象的关系 */
		@Override
		public boolean isViewFromObject(View arg0, Object arg1) {
			return arg0 == arg1;
		}
		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			ImageView view=(ImageView) object;
			convertView.add(view);// 把移除的对象 添加到缓存集合中
			container.removeView(view);
		}
		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			int index=position%datas.size();//访问网络需要这个参数
			ImageView view;
			if(convertView.size()>0){
				view=convertView.remove(0);
			}else{
				view= new ImageView(UiUtils.getContext());
			}
			bitmapUtils.display(view, HttpHelper.URL + "image?name="
					+ datas.get(index));
			container.addView(view); // 加载的view对象
			return view; // 返回的对象
		}
	}
}

UiUtils 添加这三个方法

代码语言:javascript
复制
  /**
     * 延迟执行 任务
     * @param run   任务
     * @param time  延迟的时间
     */
    public static void postDelayed(Runnable run, int time) {
        BaseApplication.getHandler().postDelayed(run, time); // 调用Runable里面的run方法
    }
    /**
     * 取消任务
     * @param auToRunTask
     */
    public static void cancel(Runnable auToRunTask) {
        BaseApplication.getHandler().removeCallbacks(auToRunTask);
    }
     
}
这样写获取到图片高的dp
 <dimen name="home_picture_height">134dp</dimen>   
public static int getDimens(int homePictureHeight) {
        return (int) getResource().getDimension(homePictureHeight);
    }

HomeFragment

代码语言:javascript
复制
public class HomeFragment extends BaseFragment {
	private List<AppInfo> datas;
	private List<String> pictures; //  顶部ViewPager 显示界面的数据
	
	// 当Fragment挂载的activity创建的时候调用
	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		show();
	}
	public View createSuccessView() {
		BaseListView listView=new BaseListView(UiUtils.getContext());
		HomePictureHolder holder=new HomePictureHolder();
		holder.setData(pictures);
		View contentView = holder.getContentView(); // 得到holder里面管理的view对象
		//contentView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
		listView.addHeaderView(contentView); // 把holder里的view对象 添加到listView的上面
		
		
		listView.setAdapter(new ListBaseAdapter(datas,listView){
			@Override
			protected List<AppInfo> onload() {
				HomeProtocol protocol=new HomeProtocol();
				List<AppInfo> load = protocol.load(datas.size());
				datas.addAll(load);
				return load;
			}
			@Override
			public void onInnerItemClick(int position) {
				super.onInnerItemClick(position);
				Toast.makeText(getActivity(), "position:"+position, 0).show();
				AppInfo appInfo = datas.get(position);
				Intent intent=new Intent(UiUtils.getContext(), DetailActivity.class);
				intent.putExtra("packageName", appInfo.getPackageName());//将包名传到详情页,详情页访问网络用包名
				startActivity(intent);
			}
			
		});
	
		// 第二个参数 慢慢滑动的时候是否加载图片 false  加载   true 不加载
		//  第三个参数  飞速滑动的时候是否加载图片  true 不加载 
		listView.setOnScrollListener(new PauseOnScrollListener(bitmapUtils, false, true));
		bitmapUtils.configDefaultLoadingImage(R.drawable.ic_default);  // 设置如果图片加载中显示的图片
        bitmapUtils.configDefaultLoadFailedImage(R.drawable.ic_default);// 加载失败显示的图片
		return listView;
	}
	
	public LoadResult load() {
		HomeProtocol protocol=new HomeProtocol();
		datas = protocol.load(0);  // load index 从哪个位置开始获取数据   0  20  40 60 
		pictures = protocol.getPictures();
		return checkData(datas);
	}
}

修改DefaultAdapter,这样传调到详情页面的时候position

已经是修改过的了,我们并不希望去点首页的图片展示

代码语言:javascript
复制
    public DefaultAdapter(List<Data> datas,ListView lv) {
        this.datas = datas;
        // 给ListView设置条目的点击事件
        lv.setOnItemClickListener(this);
        this.lv=lv;
    }
     
    // ListView 条目点击事件回调的方法
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
        //Toast.makeText(UiUtils.getContext(), "position:"+position, 0).show();
        position=position-lv.getHeaderViewsCount();// 获取到顶部条目的数量   位置去掉顶部view的数量
        onInnerItemClick(position);
    }
/**在该方法去处理条目的点击事件*/
    public void onInnerItemClick(int position) {
         
    }

面向holder编程

代码语言:javascript
复制
public View createSuccessView() {
        BaseListView listView=new BaseListView(UiUtils.getContext());
        HomePictureHolder holder=new HomePictureHolder();
        holder.setData(pictures);
        View contentView = holder.getContentView(); // 得到holder里面管理的view对象
        contentView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
        listView.addHeaderView(contentView); // 把holder里的view对象 添加到listView的上面
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015-11-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档