Android-MVP+Retrofit+Rxjava实现一个知乎日报客户端

使用MVP+Retrofit+Rxjava实现一个知乎日报客户端,界面基于Material design,还没有全部完成orz,,放假太懒

效果图



开源项目


name introduction
butterknife Annotate fields with @BindView and a view ID for Butter Knife to find and automatically cast the corresponding view in your layout.
MaterialTabs Custom Tabs with Material Design animations for pre-Lollipop devices
materialdatetimepicker Pick a date or time on Android in style
agendacalendarview This library replicates the basic features of the Calendar and Agenda views from the Sunrise Calendar (now Outlook) app, coupled with some small design touch from the Google Calendar app.

使用Material Design



可以参考我的另外一篇文章Android-Material Design的使用

列表使用的为recyclerView,这个就不解释了

tabs标题栏的实现采用了开源项目neokree/MaterialTabs

需和ViewPager一起使用。在ViewPager中添加Fragment

Activity需要 implements MaterialTabListener

fragmentList = new ArrayList<>();
        fragmentList.add(new NewsFragment());
        fragmentList.add(new TestFragment());
        fragmentList.add(new TestFragment());

        tabHost = (MaterialTabHost) this.findViewById(R.id.materialTabHost);
        pager = (ViewPager) this.findViewById(R.id.viewpager);

        // init view pager
        fragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), fragmentList);
        pager.setAdapter(fragmentPagerAdapter);
        pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                // when user do a swipe the selected tab change
                tabHost.setSelectedNavigationItem(position);
            }
        });

        // insert all tabs from pagerAdapter data
        List<String> tabsNames = new ArrayList<>();
        tabsNames.add("zhihu");
        tabsNames.add("schedule");
        tabsNames.add("timeTable");
        for (int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
            tabHost.addTab(
                    tabHost.newTab()
                            .setText(tabsNames.get(i))
                            .setTabListener(this)
            );
        }

点击fab出现日历来选择时间,用来查询过往的日报

日历的实现来自wdullaer/MaterialDateTimePicker

返回的日期需要格式化,使用在知乎日报的API中

 String date = String.format("%d%02d%02d", year, monthOfYear + 1, dayOfMonth);

知乎日报的数据



来自知乎日报 API 分析

最新消息

URL: http://news-at.zhihu.com/api/4/news/latest

过往消息

URL: http://news-at.zhihu.com/api/4/news/before/20131119

响应为

{
    date: "20140523",
    stories: [
        {
            title: "中国古代家具发展到今天有两个高峰,一个两宋一个明末(多图)",
            ga_prefix: "052321",
            images: [
                "http://p1.zhimg.com/45/b9/45b9f057fc1957ed2c946814342c0f02.jpg"
            ],
            type: 0,
            id: 3930445
        },
    ...
    ],
    ...
}

消息内容获取与离线下载

URL: http://news-at.zhihu.com/api/4/news/{id}

利用Android studio的插件GsonFormat,来解析返回的json数据

MVP+Retrofit+Rxjava


MVP

可以参考

java-mvp模式简单实现

浅谈Andorid开发中的MVP模式

Retrofit

Android网络请求库 - Say hello to retrofit

RxJava 与 Retrofit 结合的最佳实践

Rxjava

给 Android 开发者的 RxJava 详解

定义接口

public interface ZhiHuService {
    @GET("api/4/news/latest")
    Observable<LatestNews> getLatestNews();

    @GET("api/4/news/before/{date}")
    Observable<LatestNews> getBeforeNews(@Path("date") String dateString);

    @GET("api/4/news/{id}")
    Observable<News> getNews(@Path("id") int id);

    @GET("api/4/story/{id}/long-comments")
    Observable<Comment> getComments(@Path("id") int id);

    @GET("api/4/story-extra/{id}")
    Observable<StoryExtra> getStroyExtra(@Path("id") int id);
}

基础url

public class Config {
    public final static String ZHIHU_URL = "http://news-at.zhihu.com/";
}

进行封装

public class ZhiHuApi {

    private static final int DEFAULT_TIMEOUT = 5;
    private ZhiHuService zhiHuService;
    private static ZhiHuApi zhiHuApi;
    private Retrofit retrofit;

    private ZhiHuApi() {
        //设置超时时间
        OkHttpClient.Builder httpcientBuilder = new OkHttpClient.Builder();

        Retrofit retrofit = new Retrofit.Builder()
                .client(httpcientBuilder.build())//
                .baseUrl(Config.ZHIHU_URL)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

       zhiHuService = retrofit.create(ZhiHuService.class);
    }

    public static ZhiHuApi getInstance(){
        if (zhiHuApi == null) {
            synchronized (ZhiHuApi.class){
                if (zhiHuApi == null){
                   zhiHuApi = new ZhiHuApi();
                }
            }
        }
        return zhiHuApi;
    }

    public void getLatestNews(Subscriber<LatestNews> subscriber){
        zhiHuService.getLatestNews()
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }
...
}

把列表的界面作为例子

定义Contract接口

public interface NewsContract {

    interface View{
        void refreshRecyclerVew(List<LatestNews.StoriesBean> storiesList);
    }

    interface Presenter{
        void getBeforeNews(String date);
        void getLatestNews();
    }

    interface model{
        void getBeforeNews(CallBackLatestNews callback, String date);
        void getLatestNews(CallBackLatestNews callback);
    }

}

View层

public class NewsFragment extends Fragment implements NewsContract.View, DatePickerDialog.OnDateSetListener {

    private static final String TAG = "NewsFragment";
    RecyclerView recyclerView;
    private NewsContract.Presenter presenter;

    public NewsFragment() {
        presenter = new NewsPresenter(this);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_zhihu_daily, container, false);

        FloatingActionButton fab = (FloatingActionButton) view.findViewById(R.id.fab);
        fab.setImageResource(R.drawable.add);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //显示日历选项
                Calendar now = Calendar.getInstance();
                DatePickerDialog dpd = DatePickerDialog.newInstance(
                        NewsFragment.this,
                        now.get(Calendar.YEAR),
                        now.get(Calendar.MONTH),
                        now.get(Calendar.DAY_OF_MONTH)
                );
                dpd.show(getActivity().getFragmentManager(), "Datepickerdialog");
            }
        });

        recyclerView = (RecyclerView) view.findViewById(R.id.latest_news_recyclerview);
        //StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(layoutManager);
       presenter.getLatestNews();

        return view;
    }

    @Override
    public void refreshRecyclerVew(List<LatestNews.StoriesBean> storiesList) {
        Log.d(TAG, "refreshRecyclerVew: ");
        NewsSummaryAdapter adapter = new NewsSummaryAdapter(storiesList);
        recyclerView.setAdapter(adapter);
    }

    @Override
    public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
        //String date = "You picked the following date: "+dayOfMonth+"/"+(monthOfYear+1)+"/"+year;
        String date = String.format("%d%02d%02d", year, monthOfYear + 1, dayOfMonth);
        presenter.getBeforeNews(date);
    }
}

定义一个回调接口

public interface CallBackLatestNews {
    public void result(List<LatestNews.StoriesBean> list);
}

Presenter层

public class NewsPresenter implements NewsContract.Presenter {

    private static final String TAG = "NewsPresenter";
    private NewsContract.View view;
    private NewsContract.model model;

    public NewsPresenter(NewsContract.View view) {
        this.view = view;
        model = new NewsModel();
    }

    @Override
    public void getBeforeNews(String date) {
        model.getBeforeNews(new CallBackLatestNews() {
            @Override
            public void result(List<LatestNews.StoriesBean> list) {
                view.refreshRecyclerVew(list);
            }
        }, date);
    }

    @Override
    public void getLatestNews() {
        Log.d(TAG, "getLatestNews: ");
        model.getLatestNews(new CallBackLatestNews() {
            @Override
            public void result(List<LatestNews.StoriesBean> list) {
                view.refreshRecyclerVew(list);
            }
        });
    }
}

model层

public class NewsModel implements NewsContract.model {

    private static final String TAG = "NewsModel";

    @Override
    public void getBeforeNews(final CallBackLatestNews callback, String date) {
        Subscriber subscriber = new Subscriber<LatestNews>() {

            @Override
            public void onCompleted() {
                Log.d(TAG, "onCompleted: ");
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(LatestNews latestNews) {
                callback.result(latestNews.getStories());
            }
        };
        ZhiHuApi.getInstance().getBeforeNews(subscriber, date);
    }

    @Override
    public void getLatestNews(final CallBackLatestNews callback) {
        Subscriber subscriber = new Subscriber<LatestNews>() {

            @Override
            public void onCompleted() {
                Log.d(TAG, "onCompleted: ");
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(LatestNews latestNews) {
                Log.d(TAG, "onNext: ");
               callback.result(latestNews.getStories());
            }
        };
        ZhiHuApi.getInstance().getLatestNews(subscriber);
    }

}

暂时只实现了知乎日报的功能,schedule和timetable还未实现。

github:https://github.com/linsawako/oneDay

时间: 2024-09-30 09:03:01

Android-MVP+Retrofit+Rxjava实现一个知乎日报客户端的相关文章

android版知乎日报客户端应用源码

如你所见,这是一个知乎日报客户端,我给它起名为:知乎小报,大家可以下载安装体验一下,见附件.IOS版本源码:http://code.662p.com/view/9004.html因为有大把的时间需要在地铁上度过,而我又喜欢知乎日报中的内容,于是就想自己也开发一个知乎日报的客户端,没有让人皱眉的启动页广告,没有应用推荐,没有后台的消息推送,只提供最初的阅读功能.经过了一段时间的开发,最初的设想已经全部完成: 最新新闻.过往的新闻的展示 下拉刷新数据 新闻正文的展示(WebView的各种使用) 正文

设计模式笔记之四:MVP+Retrofit+RxJava组合使用

本博客转自郭霖公众号:http://mp.weixin.qq.com/s?__biz=MzA5MzI3NjE2MA==&mid=2650236866&idx=1&sn=da666831f67303eeb7a57c1591204b43&scene=24&srcid=0910wJAKSLdsEFTBKwKfTNor#wechat_redirect http://blog.csdn.net/qq_27778869/article/details/52121208 MVP

知乎日报客户端应用ios源码

swift开发的知乎日报客户端详细源码,里面分UI和网络两个模块. 1.涉及到了大部分的UI控件的使用(甚至包括UIRefreshView,UITableConrol等等)2.Connection完成网络的交互操作3.json格式的数据解析4.sqlite数据库的各种常用操作5.包含swift开发过程中常用的工具类它能帮助开发者快速的进入到swift的开发中,而不需要慢慢的去学习swift的基本语法,能快速的提高swift的运用能力. <ignore_js_op>   <ignore_j

Android MVP 利用rxjava 避免向Model传入监听方法

传统的MVP: 1.抽离出View的接口,即ILoginView. 2.抽离Model的接口,即ILoginModel. 3.抽离Presenter的接口,即ILoginPresenter. 4.实现ILoginView 接口的 LoginActivity. 5.实现ILoginModel 接口的 LoginModel. 6.实现ILoginPresenter 接口的 LoginPresenter. LoginActivity:实现ILoginView 接口以及初始化ILoginPresente

mvp+retrofit+rxjava

引用 "retrofit" : "com.squareup.retrofit2:retrofit:2.0.1", "retrofit-adapter" : "com.squareup.retrofit2:adapter-rxjava:2.0.1", "retrofit-converter" : "com.squareup.retrofit2:converter-gson:2.0.1",

swift学习第五天 项目实战-知乎日报客户端(一)网络交互NSURLConnection

CSDN下载地址:http://download.csdn.net/detail/guchengyunfeng/7989139 这篇文章主要介绍知易客户端开发的网络部分 网络接口 格式: 协议1: http://news-at.zhihu.com/api/3/news/latest (新闻列表) 协议2: http://news-at.zhihu.com/api/3/news/ (新闻详细) 代码实现的主要思路: 协议1 在KDNewsListApi类,并且实现下面的方法 1 func getN

swift学习第六天 项目实战-知乎日报客户端(二)界面开发UITableView

现在我们可以将上章节里面从服务器获取的json数据显示到界面上了,这里我们用UITableView来显示. 首先我们自定义一个UITableViewCell,命名为NewsCell,操作步骤如下: 这样会得到下面的文件: 好了,cell制作完之后,我们开始初始化UITableView //tableView tabNewList.delegate=self tabNewList.dataSource=self var nib = UINib(nibName:"NewsCell", bu

Android 基于ijkplayer+Rxjava+Rxandroid+Retrofit2.0+MVP+Material Design的android万能播放器aaa

MDPlayer万能播放器 MDPlayer,基于ijkplayer+Rxjava+Rxandroid+Retrofit2.0+MVP+Material Design的android万能播放器,可以播放本地和在线视频,可以浏览宅男杀手妹纸图片,UI设计遵循 Material Design. GitHub地址:https://github.com/Dawish/MDPlayer UI浏览:         1.UI设计: 列表使用RecyclerView,item为CardView并设置rippl

一个开源「知乎日报」Android 客户端

开源知乎日报客户端 - ZhihuPaper 介绍 如你所见,这是一个知乎日报客户端. 因为有大把的时间需要在地铁上度过,而我又喜欢知乎日报中的内容,于是就想自己也开发一个知乎日报的客户端. 经过了一段时间的准备,已经初具规模,实现了以下功能: 基础框架的搭建 列表展示当天的最新新闻 下拉刷新 正文信息展示 离线下载 还有以下功能等待实现: 下拉展示更多新闻 内容分享至SNS 正文中图片保存 无图模式开发 已读.未读 收藏夹 夜间模式 bug fix 本程序依赖: Croton SmoothPr