技术日报开源项目

时间:2022-11-08 08:51:57

        项目介绍:项目分为资讯和图片和关于三大类,资讯分为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