最近开发的项目中有类似网易新闻的频道管理,在完成项目后,我将频道管理单独抽取成Library,方便以后开发,也把总结到的一点知识分享出来。先看看,我的频道管理有什么特点吧。
1.支持固定频道,支持排序,删除。删除,添加皆有动画效果。
2.在排序完成后,通过刷新Adapter而不是重新创建Adapter,性能更好,没有卡顿。
3.使用简单方便,Library中已经封装了数据库操作,获取需要显示的数据只需要一行代码即可
final List showChannels = dataHelepr.getShowChannels(alldata);
1.添加channellib到你的项目
2.让你的JavaBean实现ChannelEntityCreater接口
import com.trs.channellib.channel.channel.ChannelEntity;
/**
* Created by zhuguohui on 2016/5/12.
*/
public class MyChannel implements ChannelEntity.ChannelEntityCreater {
...
@Override
public ChannelEntity createChannelEntity() {
ChannelEntity entity=new ChannelEntity();
//是否是固定频道
entity.setFixed(isFix==1);
//显示的名称
entity.setName(title);
return entity;
}
}
3.在你的Activity中示例化ChannelDataHelepr,注意ChannelDatahelper需要一个泛型参数,即你用来表示频道的JavaBean
ChannelDataHelepr dataHelepr;
dataHelepr = new ChannelDataHelepr(this, this, findViewById(R.id.top_bar));
构造函数声明如下,第一个为上下文,第二个为用来相应频道管理的监听器,第三个为需要将频道管理显示在哪个控件下方。
public ChannelDataHelepr(@NonNull Context context, @NonNull ChannelDataRefreshListenter channelDataRefreshListenter, @NonNull View showView)
ChannelDataRefreshListenter 声明
public static interface ChannelDataRefreshListenter {
//此方法为刷新数据的方法,只有在频道发生变化的时候才会触发
public void updateData();
//此方法为,点击频道中的item时触发,可根据是否有更新选择,ViewPager切换的时机
public void onChannelSeleted(boolean update, int posisiton);
}
如我的Activity中这两个方法的实现
@Override
public void updateData() {
loadData();
}
@Override
public void onChannelSeleted(boolean update,final int posisiton) {
//如果频道没有改变,则立即调整,否则记录下需要调整的position,在数据更新后调整
if(!update) {
viewPager.setCurrentItem(posisiton);
}else {
needShowPosition=posisiton;
}
}
4.设置用于触发频道管理的View
dataHelepr.setSwitchView(switch_view);
5.在每次数据加载完成后,过滤一遍,只显示订阅的频道。
private void loadData() {
new Thread(new Runnable() {
@Override
public void run() {
String data = getFromRaw();
List alldata = GsonUtil.jsonToBeanList(data, MyChannel.class);
//过滤数据,如果有新的频道会自动订阅并保存到数据库。
final List showChannels = dataHelepr.getShowChannels(alldata);
runOnUiThread(new Runnable() {
@Override
public void run() {
myChannels.clear();
myChannels.addAll(showChannels);
adapter.notifyDataSetChanged();
if(needShowPosition!=-1){
viewPager.setCurrentItem(needShowPosition);
needShowPosition=-1;
}
}
});
}
}).start();
}
6.为了实现Adapter可以重排序,需要这样实现Adpater,关于原理可以查看我之前的一篇博客ViewPager重排序与更新
public class TitleFragmentAdapter extends FragmentPagerAdapter {
List channels;
int id=1;
Map IdsMap=new HashMap<>();
List preIds=new ArrayList<>();
public TitleFragmentAdapter(FragmentManager fm,@NonNull List channels) {
super(fm);
this.channels=channels;
}
@Override
public Fragment getItem(int position) {
SimpleTitleFragment fragment=new SimpleTitleFragment();
Bundle bundle=new Bundle();
bundle.putString(SimpleTitleFragment.KEY_TITLE,channels.get(position).getTitle());
bundle.putString(SimpleTitleFragment.KEY_URL,channels.get(position).getUrl());
fragment.setArguments(bundle);
return fragment;
}
@Override
public int getCount() {
return channels.size();
}
@Override
public CharSequence getPageTitle(int position) {
return channels.get(position).getTitle();
}
@Override
public long getItemId(int position) {
return IdsMap.get(getPageTitle(position));
}
@Override
public int getItemPosition(Object object) {
SimpleTitleFragment fragment= (SimpleTitleFragment) object;
String title=fragment.getTitle();
int preId = preIds.indexOf(fragment.getTitle());
int newId=-1;
int i=0;
int size=getCount();
for(;iif(getPageTitle(i).equals(fragment.getTitle())){
newId=i;
break;
}
}
if(newId!=-1&&newId==preId){
return POSITION_UNCHANGED;
}
if(newId!=-1){
return newId;
}
return POSITION_NONE;
}
@Override
public void notifyDataSetChanged() {
for(MyChannel info:channels){
if(!IdsMap.containsKey(info.getTitle())){
IdsMap.put(info.getTitle(),id++);
}
}
super.notifyDataSetChanged();
preIds.clear();
int size=getCount();
for(int i=0;i
关于频道管理控件的实现可以查看这里
使用ItemTouchHelper高效地实现 今日头条 、网易新闻 的频道排序、移动
我在这个控件的基础上,添加了固定频道的功能,需要注意的是,使用这个控件时其父容器必须是FrameLayout否则会出现动画异常的情况。
https://github.com/zhuguohui/ChannelMangerDemo