技术日报开源项目

        项目介绍:项目分为资讯和图片和关于三大类,资讯分为github、hacker、SegmentFault、jobBole、技术头条、Android、ios、和all,图片是美女福利图片、并提供下载。

项目已在应用宝上线:地址http://android.myapp.com/myapp/detail.htm?apkName=com.infomation.haiffeng

项目用到的技术框架
1:采用okhttp3+retrofit2+rxjava+rxandroid+hawk+logging搭建的网络模块,支持离线缓存阅读模式。
2:其他第三方:采用picasso作为图片加载,easyrecyclerview、butterknife、bottom-navigation-bar
3:采用的第三方api:http://geekvi.net/ 和 http://gank.io/
4:根据功能模块分包,采用material design风格设计

效果如图:

1、网络模块,采用的okhttp3+retrofit2封装,是在henlin封装的基础上二次封装,缓存+生命周期。由于是请求不同的Api地址,所以有两个ApiService

public class Api {
    private static ApiService SERVICE,SERVICEG;
    /**
     * 请求超时时间
     */
    private static final int DEFAULT_TIMEOUT = 10000;

    public static ApiService getDefault() {
        if (SERVICE == null) {
            //手动创建一个OkHttpClient并设置超时时间
            OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
            httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
            httpClientBuilder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.HEADERS));
            /**
             *  拦截器
             */
            httpClientBuilder.addNetworkInterceptor(new Interceptor() {
                @Override
                public okhttp3.Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    HttpUrl.Builder authorizedUrlBuilder = request.url()
                            .newBuilder();
                            //添加统一参数 如手机唯一标识符,token等
//                            .addQueryParameter("key1","value1")
//                            .addQueryParameter("key2", "value2");
                    Request newRequest = request.newBuilder()
                            //对所有请求添加请求头
//                            .header("mobileFlag", "adfsaeefe").addHeader("type", "4")
                            .method(request.method(), request.body())
                            .url(authorizedUrlBuilder.build())
                            .build();
                    return  chain.proceed(newRequest);
                }
            });
            SERVICE = new Retrofit.Builder()
                    .client(httpClientBuilder.build())
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .baseUrl(Url.BASE_URL)
                    .build().create(ApiService.class);
        }
        return SERVICE;
    }

    public static ApiService getGankDefault() {
        if (SERVICEG == null) {
            //手动创建一个OkHttpClient并设置超时时间
            OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
            httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
            httpClientBuilder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.HEADERS));
            /**
             *  拦截器
             */
            httpClientBuilder.addNetworkInterceptor(new Interceptor() {
                @Override
                public okhttp3.Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    HttpUrl.Builder authorizedUrlBuilder = request.url()
                            .newBuilder();
                    //添加统一参数 如手机唯一标识符,token等
//                            .addQueryParameter("key1","value1")
//                            .addQueryParameter("key2", "value2");
                    Request newRequest = request.newBuilder()
                            //对所有请求添加请求头
//                            .header("mobileFlag", "adfsaeefe").addHeader("type", "4")
                            .method(request.method(), request.body())
                            .url(authorizedUrlBuilder.build())
                            .build();
                    return  chain.proceed(newRequest);
                }
            });
            SERVICEG = new Retrofit.Builder()
                    .client(httpClientBuilder.build())
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .baseUrl(Url.GBASE_URL)
                    .build().create(ApiService.class);
        }
        return SERVICEG;
    }
}
有两个解析器
/**
     * geek的api
     * @param <T>
     * @return
     */
    public static <T> Observable.Transformer<HttpResult<T>, T> handleResult(final ActivityLifeCycleEvent event, final PublishSubject<ActivityLifeCycleEvent> lifecycleSubject) {
        return new Observable.Transformer<HttpResult<T>, T>() {
            @Override
            public Observable<T> call(Observable<HttpResult<T>> tObservable) {
                Observable<ActivityLifeCycleEvent> compareLifecycleObservable =
                        lifecycleSubject.takeFirst(new Func1<ActivityLifeCycleEvent, Boolean>() {
                            @Override
                            public Boolean call(ActivityLifeCycleEvent activityLifeCycleEvent) {
                                return activityLifeCycleEvent.equals(event);
                            }
                        });
                return tObservable.flatMap(new Func1<HttpResult<T>, Observable<T>>() {
                    @Override
                    public Observable<T> call(HttpResult<T> result) {
                        if ("OK".equals(result.getMessage())) {
                            return createData(result.getData());
                        } else {
                            return Observable.error(new ApiException(0));
                        }
                    }
                }).takeUntil(compareLifecycleObservable).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).subscribeOn(AndroidSchedulers.mainThread()).observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

    /**
     * gank.io的api
     * @param <T>
     * @return
     */
    public static <T> Observable.Transformer<GHttpResult<T>, T> handleResultG(final ActivityLifeCycleEvent event, final PublishSubject<ActivityLifeCycleEvent> lifecycleSubject) {
        return new Observable.Transformer<GHttpResult<T>, T>() {
            @Override
            public Observable<T> call(Observable<GHttpResult<T>> tObservable) {
                Observable<ActivityLifeCycleEvent> compareLifecycleObservable =
                        lifecycleSubject.takeFirst(new Func1<ActivityLifeCycleEvent, Boolean>() {
                            @Override
                            public Boolean call(ActivityLifeCycleEvent activityLifeCycleEvent) {
                                return activityLifeCycleEvent.equals(event);
                            }
                        });
                return tObservable.flatMap(new Func1<GHttpResult<T>, Observable<T>>() {
                    @Override
                    public Observable<T> call(GHttpResult<T> result) {
                        if ("false".equals(result.getError())) {
                            return createData(result.getResults());
                        } else {
                            return Observable.error(new ApiException(0));
                        }
                    }
                }).takeUntil(compareLifecycleObservable).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).subscribeOn(AndroidSchedulers.mainThread()).observeOn(AndroidSchedulers.mainThread());
            }
        };
    }
界面主要是 bottom-navigation-bar+fragment+easyrecyclerview。

public void initView() {
        bottomNavigationBar.setMode(BottomNavigationBar.MODE_SHIFTING);
        bottomNavigationBar.setBackgroundStyle(BottomNavigationBar.BACKGROUND_STYLE_RIPPLE);
        bottomNavigationBar.addItem(new BottomNavigationItem(R.mipmap.information, "文章").setActiveColorResource(R.color.colorPrimary))
                .addItem(new BottomNavigationItem(R.mipmap.tuku, "图库").setActiveColorResource(R.color.colorAccent))
                .addItem(new BottomNavigationItem(R.mipmap.about, "关于").setActiveColorResource(R.color.colorJu))
                .setFirstSelectedPosition(0)
                .initialise();

        getFragments();
        setDefaultFragment();
        bottomNavigationBar.setTabSelectedListener(this);
    }

    public void getFragments() {
        fragments = new ArrayList<>();
        InformationFragment informationFragment = new InformationFragment();
        GalleryFragment galleryFragment = new GalleryFragment();
        AboutFragment aboutFragment = new AboutFragment();
        fragments.add(informationFragment);
        fragments.add(galleryFragment);
        fragments.add(aboutFragment);
    }

    public void setDefaultFragment() {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction =  fragmentManager.beginTransaction();
        transaction.replace(R.id.frame_layout,fragments.get(0));
        transaction.commit();
    }

    @Override
    public void onTabSelected(int position) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction =  fragmentManager.beginTransaction();
        if (fragments.get(position).isAdded()){
            transaction.hide(fragments.get(mLastPosition)).show(fragments.get(position));
        }else{
            transaction.hide(fragments.get(mLastPosition)).add(R.id.frame_layout,fragments.get(position));
        }
        transaction.commit();
        mLastPosition = position;
    }
分享采用的是系统自带的分享
@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu,menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.action_share_url:
                shareUrl();
                break;
        }
        return super.onOptionsItemSelected(item);
    }
   public void shareUrl(){
        String url = webView.getUrl();
        Intent shareIntent = new Intent();
        shareIntent.setAction(Intent.ACTION_SEND);
        shareIntent.putExtra(Intent.EXTRA_TEXT, url);
        shareIntent.setType("text/plain");
        startActivity(Intent.createChooser(shareIntent, "分享到"));
    }
图片下载采用的是picasso
Target target = new Target(){
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {

                File imgFile = new File(savePath);
                FileOutputStream ostream = null;
                try {
                    ostream = new FileOutputStream(imgFile);
                    if (savePath.contains(".PNG")|| savePath.contains(".png")){
                        bitmap.compress(Bitmap.CompressFormat.PNG, 100, ostream);
                    }else if (savePath.contains(".JPG")|| savePath.contains(".jpg")) {
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, ostream);
                    }
                    ostream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                Toast.makeText(ImgLookActivity.this,"图片下载至:"+ savePath,Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onBitmapFailed(Drawable errorDrawable) {

            }

            @Override
            public void onPrepareLoad(Drawable placeHolderDrawable) {

            }
        };
        Picasso.with(this).load(mData.get(mPosition)).into(target);
以上就是部分源码

github地址:https://github.com/Ahuanghaifeng

欢迎下载使用和star




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值