前言

最开始学习写应用的时候,发现类聚合数据这个平台可以提供一些免费数据接口,于是写了个人的第一个应用—– JuheNews,当时的知识储备稍显粗糙,虽然现在的知识也不咋滴,但是相对之前而言还是有些进步的,所以决定将应用重构一下,具体参考我的第二个个人开发的应用— GankIOClient,采用类似的技术思路,重构后两个应用在代码结构上是很相似的。

技术选型

1. 下拉刷新 + 加载更多

采用BGARefreshLayout-Android,支持的下拉刷新样式基本可以满足我的需求,使用起来也比较简单,实现两个接口即可设置刷新动作和加载更多的动作。这位卓友的其他开源库也很好用,有兴趣的可以去看下。

使用方法:

private void initBGALayout() {
    // 为BGARefreshLayout 设置代理
    bgaRefreshLayout.setDelegate(this);
    // 设置下拉刷新和上拉加载更多的风格     参数1:应用程序上下文,参数2:是否具有上拉加载更多功能

    BGANormalRefreshViewHolder refreshViewHolder =
            new BGANormalRefreshViewHolder(getContext(), true);
    refreshViewHolder.setLoadingMoreText("加载更多");
    refreshViewHolder.setLoadMoreBackgroundColorRes(R.color.white);
    refreshViewHolder.setRefreshViewBackgroundColorRes(R.color.white);
    bgaRefreshLayout.setRefreshViewHolder(refreshViewHolder);
}
    @Override
    public void onBGARefreshLayoutBeginRefreshing(BGARefreshLayout refreshLayout) {
    //执行下拉刷新操作
    }

    @Override
    public boolean onBGARefreshLayoutBeginLoadingMore(BGARefreshLayout refreshLayout) {
        //执行加载更多操作,返回false代表不支持加载更多
        return false;
    }

2. 网络请求

Retrofit + RxJava2,这个就不用多做介绍了,最开始学习这两个内容的时候读过的文章分享一下:

RxJava 与 Retrofit 结合的最佳实践

给 Android 开发者的 RxJava 详解

我的一个RxJava2文章收藏集

这位朋友写的通俗易懂,不看Rxjava2的官文应该也能很快的了解Rxjava升级到2之后的变化。

使用方法:

public interface JuheApi {
    @GET
    Observable<NewsBean> getNews(@Url String url);

    @GET
    Observable<FunnyBean> getFunny(@Url String url);

    @GET
    Observable<JokeBean> getJoke(@Url String url);

    @GET
    Observable<HistoryBean> getTodayInHistory(@Url String url);

    @GET
    Observable<QueryNewsBean> getQueryNews(@Url String url);
}
public class Retrofitance {
    public static final String BASE_URL = "http://gank.io/api/";

    private static final int DEFAULT_TIMEOUT = 5;

    private Retrofit retrofit;
    private JuheApi mJuheApi;
    private OkHttpClient mOkHttpClient;

    //构造方法私有
    private Retrofitance() {
        //手动创建一个OkHttpClient并设置超时时间
        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
        httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        mOkHttpClient = httpClientBuilder.build();

        retrofit = new Retrofit.Builder().client(mOkHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(BASE_URL)
                .build();

        mJuheApi = retrofit.create(JuheApi.class);
    }

    //获取单例
    public static Retrofitance getInstance() {
        return SingletonHolder.INSTANCE;
    }

    /**
     * 根据类型获取新闻信息
     */
    public void getNews(Observer<NewsBean> subscriber, String type) {
        String URL = "";
        commonOp(mJuheApi.getNews(URL),subscriber);
    }

    /**
     * 获取趣图信息
     */
    public void getFunny(Observer<FunnyBean> subscriber, int pagenum) {
        String URL ="";
        commonOp(mJuheApi.getFunny(URL), subscriber);
    }

    /**
     * 获取历史上的今天
     */
    public void getHistory(Observer<HistoryBean> subscriber) {
        Calendar now = Calendar.getInstance();
        String URL = "";
        commonOp(mJuheApi.getTodayInHistory(URL),subscriber);
    }

    /**
     * 获取笑话大全
     */
    public void getJoke(Observer<JokeBean> subscriber, int pagenum) {
        String URL ="";
        commonOp(mJuheApi.getJoke(URL), subscriber);
    }

    public void getQueryNews(Observer<QueryNewsBean> subscriber, String keyword) {
        String URL = "";
        commonOp(mJuheApi.getQueryNews(URL), subscriber);
    }

    private void commonOp(Observable observable, Observer subscriber) {
        observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }
    //在访问HttpMethods时创建单例
    private static class SingletonHolder {
        private static final Retrofitance INSTANCE = new Retrofitance();
    }
}

3. 响应式编程

不二选择,RxJava2 + RxAndoid,告别Thread和AsyncTask,不用写Handler了。

使用方法:

public void getContent(int pagenum) {
    Observer<FunnyBean> observer = new Observer<FunnyBean>() {
        @Override
        public void onComplete() {
            endLoading();
        }

        @Override
        public void onError(Throwable e) {
            e.printStackTrace();
            endLoading();
            onNetworkError();
        }

        @Override
        public void onSubscribe(Disposable d) {

        }

        @Override
        public void onNext(FunnyBean funnyBean) {
            if (bgaRefreshLayout.isLoadingMore()) {
            } else {
                mVisitableList.clear();
            }
            if (funnyBean.getResult() == null || funnyBean.getResult().getData() == null
                    || funnyBean.getResult().getData().size() == 0) {
                onDataEmpty();
            } else {
                mVisitableList.addAll(funnyBean.getResult().getData());
            }
            mMultiRecyclerAdapter.setData(mVisitableList);
        }
    };
    Retrofitance.getInstance().getFunny(observer, pagenum);
}

4. 多类型RecyclerView Item实现

参考博文RecyclerView多类型Item的正确实现姿势

当然你也可以选择一些开源库,只是我习惯了使用这种方式,用起来也比较顺手。思路和实现方式也比较简单,使用接口化的数据和泛型,抽取抽象类,结构分明,扩展性强,聪明的你应该一看就会懂。

具体使用方法参考项目代码或者是上面这篇博文,涉及的代码比较多,主要是稍微有点结构化,不便列举。


5. 注解

butterknife,告别findViewById,但是有了Kotlin,我觉得我们也可以告别butterknife了,毕竟一把小刀。

使用方法:

@BindView(R.id.tl_web)
Toolbar tlWeb;
@BindView(R.id.wv_content)
WebView wvContent;
@BindView(R.id.activity_web)
LinearLayout activityWeb;
@BindView(R.id.progressbar)
ProgressBar progressbar;

....
ButterKnife.bind(this);

配合插件使用效果会更好喔。


6. 图片加载

我首选Glide,因为我有GIF的需求,Picasso不支持GIF,虽然体量比较小。

Glide的使用方法参考官文,最近Glide有大版本升级,改动比较多,有兴趣的可以关注下

使用方法:

Glide.with(itemView.getContext()).load(pic1path).placeholder(R.mipmap.empty_data).into(imageView);

Glide有更高阶的使用方法,根据需求学习吧。


7. 数据解析

Gson,Google的开源库,基本可以满足我的开发需求,暂时没有尝试过其他的。

使用的过程中配合Retrofit使用

compile 'com.squareup.retrofit2:converter-gson:2.1.0'
retrofit = new Retrofit.Builder().client(mOkHttpClient)
                /*This is the key*/
               .addConverterFactory(GsonConverterFactory.create())         .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(BASE_URL)
                .build();

配合插件使用效果会更好:GsonFormat


8. 界面布局

采用TabHost + Framgnet可以满足日常需求,当然使用开源库FlycoTabLayout更是可以构建出炫酷的Tab页面,配合上Fragment,基本可以满足需求。

使用方法:

switch (i) {
    case 0:
        textView.setText("资讯");
        imageView.setImageResource(R.drawable.news);
        tabHost.addTab(tabHost.newTabSpec("1").setIndicator(view).setContent(
                R.id.frag_news));
        break;
    case 1:
        textView.setText("笑话");
        imageView.setImageResource(R.drawable.joke);
        tabHost.addTab(tabHost.newTabSpec("2").setIndicator(view).setContent(
                R.id.frag_joke));
        break;
    case 2:
        textView.setText("趣图");
        imageView.setImageResource(R.drawable.funny);
        tabHost.addTab(tabHost.newTabSpec("3").setIndicator(view).setContent(
                R.id.frag_funny));
        break;
    case 3:
        textView.setText("历史");
        imageView.setImageResource(R.drawable.history);
        tabHost.addTab(tabHost.newTabSpec("4").setIndicator(view).setContent(
                R.id.frag_history));
        break;
    default:
        break;
}

FlycoTabLayout的使用方法参考官文或者网上如海水般的博文。


9. 内容搜索

自定义Toolbar这个时候就显示出来威力。简单的一个文本框和一个若隐若现的搜索按钮,满足需求。开源库也有一些,但是适合我自己的不太多,所以基本上我都是如上实现。

使用方法:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar_search"
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:fitsSystemWindows="true"
    android:background="@color/colorToolbar">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <EditText
            android:id="@+id/et_search"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_marginBottom="8dp"
            android:layout_marginTop="8dp"
            android:layout_weight="6"
            android:background="@drawable/search_edittext_bg"
            android:padding="2dp"
            android:textColor="@color/colorBlack"
            android:textSize="12sp"/>

        <Button
            android:id="@+id/bt_search"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:clickable="false"
            android:gravity="center"
            android:text="搜索"
            android:background="@color/colorToolbar"
            android:textColor="@color/colorToolbar"
            android:textSize="14sp"/>
    </LinearLayout>
</android.support.v7.widget.Toolbar>

10. 版本更新

第三方服务 。我使用的是Fir.im,相对比较好用,利用提供的版本接口检测版本更新。然后本地下载或者跳转到浏览器下载应用,完成安装,都是不错的选择。类似的平台还有很多,可以网上搜索一下。

Android 开发技术选型(博客,新闻,阅读类)的更多相关文章

  1. android开发进阶学习博客资源

    Android开发者博客推荐 Android入门级 - 罗宪明 http://blog.csdn.net/wdaming1986 Android入门级 - 魏祝林 http://blog.csdn.n ...

  2. [Android开发系列]IT博客应用

    1.关于坑 好吧,在此之前先来说一下,之前开的坑,恩,确实是坑,前面开的两个android开发教程的坑,对不起,实在是没什么动力了,不过源码都有的,大家可以参照github这个应用 https://g ...

  3. 完整Android开发基础入门博客专栏

    博客地址:http://www.runoob.com/w3cnote/android-tutorial-contents.html

  4. [Android开发系列]IT博客应用V1.3

    首先,感谢使用这款软件并给我意见的朋友们,有你们的意见,才有了这个版本. 其次,检索功能和分类筛选功能(如果是你提的意见,记得在下面mark哦,毕竟读代码你能发现,其实发意见这个就是用自己的邮箱给自己 ...

  5. 一步步开发自己的博客 .NET版 剧终篇(6、响应式布局 和 自定义样式)

    前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做 ...

  6. 一步步开发自己的博客 .NET版(1、基本显示)

    前言 我们每个猿都有一个搭建自己独立博客的梦,我也不例外.以前想 现在想 以后也想.之所以一直迟迟没有着手,是因为难以跨出第一步.每次心里想着,等我以后技术好了再说,然后就没有然后了.以前用过word ...

  7. 一步步开发自己的博客 .NET版(3、注册登录功能)

    前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做 ...

  8. 一步步开发自己的博客 .NET版(4、文章发布功能)百度编辑器

    前言 这次开发的博客主要功能或特点: 第一:可以兼容各终端,特别是手机端. 第二:到时会用到大量html5,炫啊. 第三:导入博客园的精华文章,并做分类.(不要封我) 第四:做个插件,任何网站上的技术 ...

  9. 一步步开发自己的博客 .NET版(5、Lucenne.Net 和 必应站内搜索)

    前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做 ...

随机推荐

  1. Linux安装ftp组件vsftpd

    1 安装vsftpd组件 安装完后,有/etc/vsftpd/vsftpd.conf 文件,是vsftp的配置文件. [root@bogon ~]# yum -y install vsftpd 2 添 ...

  2. This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' 解决办法

    背景:mysql5.1.36,mybatis 前言:为了解决一对多,分页显示,但是前端主要是显示的一的一方的数据和(多方的某个字段拼接在一起),此时的limit不能直接跟在查询的后面,需要用子查询把需 ...

  3. com.mysql.jdbc.MysqlDataTruncation:Data Truncation:Data too long for column '字段name' at row 1

    1.问题描述: 在mysql插入数据的时候报错:Cause: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long fo ...

  4. System.IO命名空间下常用的类

    System.IO System.IO.Directory 目录 System.IO.Path 文件路径(包含目录和文件名) System.IO.FileInfo 提供创建.复制.删除.移动和打开文件 ...

  5. 爬虫之JSON案例

    糗事百科实例: 爬取糗事百科段子,假设页面的URL是 http://www.qiushibaike.com/8hr/page/1 要求: 使用requests获取页面信息,用XPath / re 做数 ...

  6. codeforces 484B - LubaAndTicket - 贪心

    2017-08-22 10:54:00 writer:pprp 题意如下: 给你6个数组,你的操作可以是更改某一位的数字成为0-9之间任意一个数,要求前三个数字的和与后三个数字的和相等. 问你最少用几 ...

  7. harbor 管理Helm Chart包

    官方网站:https://github.com/goharbor/harbor官方用户手册:https://github.com/goharbor/harbor/blob/master/docs/us ...

  8. ABP 源码分析汇总之 AutoMapper

    AutoMapper 是一个对象映射工具, 安装时只需要安装 如下即可: 有关于它的介绍,参考官网:http://automapper.org/ AutoMapper使用比较简单,还是直奔主题,看一下 ...

  9. matlab C++ (VS Qt)混合编程 / mxArray / QT5中文乱码

    一.混合编程环境搭建---依据我的情况,分成了4个部分: 1:破解matlab,因为matlab破解不完全,编译器不能使用,会出错.(参考https://blog.csdn.net/a12593012 ...

  10. hadoop2.6.0集群配置

    1.修改机器名 集群的搭建最少需要三个节点,机器名分别修改为master,slave1,slave2.其中以master为主要操作系统. 修改hostname: sudo gedit /etc/hos ...