本项目实现了影视综艺榜单及其历史数据查询,实现个人页面展示、个人页面粉丝和关注列表、个人页面已发布视频列表及其详情页
https://github.com/gujunhe/douyin
https://github.com/gujunhe/douyin
团队成员 | 主要贡献 |
---|---|
我 | 负责基础架构、网络框架、room框架搭建、个人页面已发布视频列表及其详情页、粉丝和关注列表 |
XX | 电影榜单、粉丝和关注列表 |
XX | 电视剧榜单、粉丝和关注列表 |
XX | 综艺榜单、导航栏搭建 |
XX | 榜单数据管理、导航栏搭建 |
XX | 影视榜单布局、个人界面布局 |
Navigation 提供路由导航服务 ViewModel 具备生命周期感知能力的数据存储组件,用于存放应用程序页面所需的数据
实现网络请求。
用来配合Retrofit、Room实现序列化和反序列化,自定义Type Converter将榜单List数据转化为Json存储到数据库中。
数据库,与LiveData、ViewModel结合使用,当Room数据库中的数据发生变化时,能够通过LiveData组件通知View层,实现数据的自动更新。
LiveData是一个可被观察的数据容器类,在ViewModel中的数据发生变化时通知页面。
使用声明性格式将布局中的界面组件绑定到应用中的数据源,使页面与布局文件之间的耦合度进一步降低。
列表分页组件,实现数据预加载、按需加载,结合Room使用,数据直接来源于Room数据库。当网络数据请求成功后,会直接将其写入Room数据库,由于使用了LiveData,当数据有变化时,ViewModel会自动得到通知,自动完成数据的更新。
加载网络图片,实现占位图、图片自动缓存。
项目通过GitHub进行团队协作开发。
本项目采用MVVM的架构,在ViewModel层和Model层之间引入Repository层。在Repository层处理本地数据和网络数据之间的业务逻辑,让Repository层对ViewModel层负责,使ViewModel只需要关心自己的业务逻辑,而不用关心数据的具体来源。数据在发生变化时,界面能够自动得到通知并进行更新,数据模型驱动界面更新。 这里以影视综艺榜单代码为例
- RankFragment持有RankViewModel,获取到来自RankViewModel的数据后将数据加载进recyclerview。
rankViewModel.getRankItemByTypeAndVersion(type, "141").observe(getViewLifecycleOwner(), new Observer<List<RankItem.DataBean.ListBean>>() {
@Override
public void onChanged(List<RankItem.DataBean.ListBean> listBeans) {
if(listBeans!=null) {
myItemRecyclerViewAdapter = new MyItemRecyclerViewAdapter(listBeans);
recyclerView.setAdapter(myItemRecyclerViewAdapter);
}
}
});
- RankViewModel持有rankRepository,通过rankRepository获取到榜单数据。
public LiveData<List<RankItem.DataBean.ListBean>> getRankItemByTypeAndVersion(String type,String version) {
return rankRepository.getRankItemByTypeAndVersion(type,version);
}
- RankRepository进行数据请求。
public LiveData<List<RankItem.DataBean.ListBean>> getRankItemByTypeAndVersion(String type,String version) {
return rankRepository.getRankItemByTypeAndVersion(type,version);
}
public void refreshitembyTypeAndVersion(String type,String version)
{
apiService.getrankitem("application/json",MyApplication.clientToken.getValue(),type,version).enqueue(new Callback<RankItem>() {
@Override
public void onResponse(Call<RankItem> call, Response<RankItem> response) {
if(response.body().getData().getList()!=null)
{
insertRankItem(response.body().getData().getList());//插入数据库
Log.d(TAG,response.body().getData().getList().toString());
}
}
@Override
public void onFailure(Call<RankItem> call, Throwable t) {
}
});
}
private void insertRankItem(List<RankItem.DataBean.ListBean> list )
{
AsyncTask.execute(new Runnable() {
@Override
public void run() {
for(int i=0;i<list.size();i++) {
Log.d(TAG, list.get(i).toString());
rankItemDao.insertRankItem(list.get(i));
}
}
});
}
- RankItemDao获取数据返回的是LiveData对象,当数据库中的数据更新后,ViewModel会自动得到通知,自动完成数据的更新。
@Dao
public interface RankItemDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertRankItem(RankItem.DataBean.ListBean rankitem);
//获取表中所有数据
@Query("SELECT *FROM rankitem WHERE type = :type")
LiveData<List<RankItem.DataBean.ListBean>> findAllbytype(String type);
}
-
adapter:各种适配器,包括自定义的ViewBindingAdapter实现直接在布局文件中通过image调用静态方法加载网络图片,FollowingPagedListAdapter和FansPagedListAdapter实现对粉丝和关注列表进行分页加载。
-
ui:activity和fragment以及对应的Viewmodel层、Repository层(部分没有使用),分页加载的SourceFactory,以及一些布局所需要的函数。
本项目所有已实现的功能经过测试无报错
有使用Androidstudio自带的Profiler和手机自带的GPU渲染进行性能测试
(影视榜单api超出限制,无法演示榜单版本切换)
- 对clientsecret、access_token没有加密保存。
- 界面不够美观。
- 没有编写 access_token过期后自动刷新的代码。
- 减少页面布局的嵌套,优化recyclerview的加载速度。
- 对一些可以复用的代码进行可扩展的封装,减少代码量,提高开发效率。
- 优化项目结构
第一次当组长通过团队协作完成项目,在通过github进行团队协作中还是遇到了不少困难,同时也学到了很多。在项目刚开始构建时,本想用模块化进行开发,以方便团队协作、开发和维护,但是后来觉得项目不大,就没有采用,后面导致团队协作遇到困难。
在模仿抖音个人界面实现下拉放大、松手自动回弹的效果时,查找了很多资料和方案,最后实现了比较好的效果,在这个过程中加深了对自定义view的理解,让自己的技术得到了提升。
由于是第一次完成一个不算小的项目,在架构方面、代码封装方面做得不太好,只是为了完成所要求的功能,没有对代码进行太多的扩展,在写代码时也没有编写详细的注释,这些方面应该要去改善。