Retrofit+Rxjava+Gson 新闻端小项目

  又到周末了,最近一周有点时间搞点东西来耍。由于工作的性质,导致我接触的互联网应用几乎没有,所以本身写的代码可能跟互联网应用有很大的差别,我会不断的更新优化应用。

  本项目最开始只是为了满足我自己搞一个Retrofit+Rxjava+Gson 的小例子,最终演变成了一个可以玩的小项目,数据来源:易源数据。后面打算加更多的内容,比如视频,图片之类的,或者登陆,设置等等,也会不断的去刚改项目的架构以及优化部分代码,后面尽量写成MVP模式的应用。

  目前这个demo,主要用到以下几个库:

    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support:design:27.1.1'
    //Retrofit网络请求框架
    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava:2.4.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
    implementation 'com.google.code.gson:gson:2.8.5'
    //下拉加载和下拉刷新
    implementation 'com.github.userswlwork:pull-to-refresh:1.0.0'
    // butterknift 框架
    implementation 'com.jakewharton:butterknife:8.5.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
    //Glide
    implementation 'com.github.bumptech.glide:glide:4.7.1'
    //网页加载动画
    implementation 'com.github.ybq:Android-SpinKit:1.1.0'
    // EventBus
    implementation 'org.greenrobot:eventbus:3.0.0'

  主要实现的功能有 新闻资源的获取解析(Retrofit+Rxjava+Gson),下拉刷新(pull-to-refresh),注解释框架ButterKnife,用Glide加载新闻列表图片,在等待网页加载时的动画效果(Android-spinkit),以及数据分发暂时用EventBus来处理,链接打开的网页,使用了腾讯的TBS x5 内核,既然是新闻类型的应用肯定是有推送的,我在这里用了极光推送,初次使用还不是太熟这个用法,只是按照自己的理解 做了一点处理,详情见demo。

  项目目前主打 新闻浏览功能,所以目前的架构还没搞, 目前整个功能项是由单个Activit+fragment+viewpage 的方式实现

package com.fly.kuaixun.ui;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.WindowManager;
import android.widget.RelativeLayout;

import com.fly.kuaixun.R;
import com.fly.kuaixun.adapter.NewsViewPagerAdapter;
import com.fly.kuaixun.tool.LogUtil;
import com.fly.kuaixun.tool.ToolsUtil;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;


public class NewsActivity extends AppCompatActivity{
    private String[] titles = new String[]{
            "头条", "社会", "国内", "国际", "娱乐",
            "体育", "军事", "科技", "财经", "时尚"};
    @BindView(R.id.tabs)
    TabLayout mTabs;
    @BindView(R.id.vp_content)
    ViewPager mVpContent;
    private NewsViewPagerAdapter mFragmentAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;
        getWindow().setFlags(flag, flag);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        loadMovieChannel();
        EventBus.getDefault().register(this);
    }
    /**
     * 加载电影频道
     */
    private void loadMovieChannel() {
        List<NewsFragment> mNewsFragmentList = new ArrayList<>();
        for (int i = 0; i < titles.length; i++) {
            mNewsFragmentList.add(createListFragments(i));
        }
        if (mFragmentAdapter == null) {
            mFragmentAdapter = new NewsViewPagerAdapter(getSupportFragmentManager(), mNewsFragmentList, Arrays.asList(titles));
        } else {
            //刷新fragment
            mFragmentAdapter.setFragments(getSupportFragmentManager(), mNewsFragmentList, Arrays.asList(titles));
        }
        mVpContent.setAdapter(mFragmentAdapter);
        mTabs.setupWithViewPager(mVpContent);
        ToolsUtil.dynamicSetTabLayoutMode(mTabs);
        mTabs.setTabTextColors(getResources().getColor(R.color.white), getResources().getColor(R.color.black));

    }

    private NewsFragment createListFragments(int index) {
        NewsFragment fragment = new NewsFragment();
        Bundle bundle = new Bundle();
        bundle.putString("type", titles[index]);
        fragment.setArguments(bundle);
        return fragment;
    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent1(String text) {
       switch (text){
           case "Jpush_message_come":
               LogUtil.e("================= 收到极光推送消息");
               showNormalDialog();
               break;
       }
    }

    /**
     *  一个dialog,用来提醒极光推送效果
     */
    private void showNormalDialog() {
        final AlertDialog.Builder
                normalDialog =
                new AlertDialog.Builder(NewsActivity.this);
        normalDialog.setTitle("您有新的消息!");
        normalDialog.setMessage("您有新的消息,请及时查阅!");
        normalDialog.show();
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }
}


 

package com.fly.kuaixun.ui;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

import com.google.gson.Gson;
import com.handmark.pulltorefresh.library.ILoadingLayout;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
import com.fly.kuaixun.R;
import com.fly.kuaixun.bean.NewBean;
import com.fly.kuaixun.bean.NewContentBean;
import com.fly.kuaixun.adapter.NewsListAdapter;
import com.fly.kuaixun.mode.NewsService;
import com.fly.kuaixun.tool.AndroidScheduler;
import com.fly.kuaixun.tool.UrlTool;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import butterknife.BindView;
import butterknife.ButterKnife;
import okhttp3.ResponseBody;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Subscriber;
import rx.schedulers.Schedulers;

public class NewsFragment extends Fragment implements AdapterView.OnItemClickListener {
    @BindView(R.id.listView)
    PullToRefreshListView listView;
    protected Handler mHandler = new Handler();
    private List<NewContentBean> news = new ArrayList<>();
    private NewsListAdapter adapter;
    private String mMovieGenres;
    private int newsPage = 1;
    private int newsPageSize;
    private Context mContext;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_news, container, false);
        ButterKnife.bind(this, view);
        initUi(view);
        return view;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext = context;
    }

    private void initUi(View view) {
        if (getArguments() != null) {
            mMovieGenres = getArguments().getString("type");
        }
        initPullToRefreshListView();
        listView.setOnItemClickListener(this);
        loadNews(mMovieGenres, newsPage);
        adapter = new NewsListAdapter(mContext, news);
        listView.setAdapter(adapter);
    }


    private void initPullToRefreshListView() {
        listView.setMode(PullToRefreshBase.Mode.BOTH);
        ILoadingLayout startLabels = listView.getLoadingLayoutProxy(true, false);
        startLabels.setPullLabel("下拉刷新");
        startLabels.setRefreshingLabel("正在刷新...");
        startLabels.setReleaseLabel("释放立即刷新");

        ILoadingLayout endLabels = listView.getLoadingLayoutProxy(false, true);
        endLabels.setPullLabel("上拉刷新");
        endLabels.setRefreshingLabel("正在载入...");
        endLabels.setReleaseLabel("释放立即刷新");
        listView.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2<ListView>() {
            @Override
            public void onPullDownToRefresh(PullToRefreshBase<ListView> pullToRefreshBase) {
                //  newsType = titles[(int) (Math.random() * (titles.length))];  //随机去掉
                newsPage = 1;
                loadNews(mMovieGenres, newsPage);
            }

            @Override
            public void onPullUpToRefresh(PullToRefreshBase<ListView> pullToRefreshBase) {
                if (newsPage == newsPageSize) {
                    Toast.makeText(getActivity(), "我是有底线的!", Toast.LENGTH_SHORT).show();
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            SystemClock.sleep(100);
                            listView.onRefreshComplete();
                        }
                    });
                    return;
                }
                newsPage++;
                loadNews(mMovieGenres, newsPage);
            }
        });
    }

    private void loadNews(String newsType, int newsPage) {
        Map<String, String> params = new HashMap<>();
        params.put("showapi_appid", UrlTool.appid);
        params.put("showapi_sign", UrlTool.secret);
        params.put("channelId", "");
        params.put("channelName", "");
        params.put("title", newsType);
        params.put("page", "" + newsPage);
        params.put("needContent", "0");
        params.put("needHtml", "0");
        params.put("needAllList", "0");
        params.put("maxResult", "50");
        params.put("id", "");
        Retrofit retrofit = new Retrofit
                .Builder()
                .baseUrl(UrlTool.APP_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        NewsService newsService = retrofit.create(NewsService.class);
        newsService.getNewsData(params).subscribeOn(Schedulers.io()).observeOn(AndroidScheduler.mainThread()).subscribe(new Subscriber<ResponseBody>() {
            @Override
            public void onCompleted() {
                listView.onRefreshComplete();
            }

            @Override
            public void onError(Throwable e) {
                listView.onRefreshComplete();
            }

            @Override
            public void onNext(ResponseBody responseBody) {
                String json = null;
                try {
                    json = new String(responseBody.bytes());

                } catch (IOException e) {
                    e.printStackTrace();
                }
                handleResult(json);
            }
        });

    }

    private void handleResult(final String json) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                news.clear();
                NewBean newBean = new Gson().fromJson(json, NewBean.class);
                NewBean.ShowapiResBodyBean.PagebeanBean pagebeanBean = newBean.getShowapi_res_body().getPagebean();
                newsPageSize = pagebeanBean.getAllPages();
                List<NewBean.ShowapiResBodyBean.PagebeanBean.ContentlistBean> contentlistBeans = newBean.getShowapi_res_body().getPagebean().getContentlist();

                for (int i = 0; i < contentlistBeans.size(); i++) {
                    int images = contentlistBeans.get(i).getImageurls().size();
                    String urls = null;
                    if (images != 0) {
                        for (int a = 0; a < images; a++) {
                            urls = contentlistBeans.get(i).getImageurls().get(0).getUrl();
                        }
                    }
                    String title = contentlistBeans.get(i).getTitle();
                    String link = contentlistBeans.get(i).getLink();
                    String source = contentlistBeans.get(i).getSource();
                    String time = contentlistBeans.get(i).getPubDate();
                    String imageUrl = null;
                    if (images == 0) {
                        imageUrl = "null_image_url";
                    } else {
                        imageUrl = urls;
                    }
                    NewContentBean contentBean = new NewContentBean();
                    contentBean.setTitle(title);
                    contentBean.setUrl(link);
                    contentBean.setSource(source);
                    contentBean.setTime(time);
                    contentBean.setImagUrl(imageUrl);
                    news.add(contentBean);
                }
                listView.getRefreshableView().setSelection(1);  //回到第一行item
                adapter.notifyDataSetInvalidated();
            }
        });
    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        startWebActivity(news.get(i - 1).getUrl());
    }

    private void startWebActivity(String url) {
        Intent intent = new Intent(mContext, WebActivity.class);
        intent.putExtra("url", url);
        startActivity(intent);
    }
}

 

package com.fly.kuaixun.mode;

import java.util.Map;

import okhttp3.ResponseBody;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
import rx.Observable;

public interface NewsService {
    @FormUrlEncoded
    @POST("109-35")
    Observable<ResponseBody> getNewsData(@FieldMap Map<String, String> params);
}

 以上三部分代码 主要就是  Retrofit +Rxjava + Gson ,以及下拉刷新的主要代码。

代码比较多,就不一一贴代码了,项目内容也是比较清晰,容易看懂的,关于极光推送的相关内容也在项目中。

本项目会一直抽空不定期更新,偶尔会加一些新的功能。

demo 源代码 在这里下载 https://github.com/mapeifan/NewsClient

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值