技术日报开源项目
2017-03-28 11:28
447 查看
项目介绍:项目分为资讯和图片和关于三大类,资讯分为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风格设计
效果如图:
![](http://img.blog.csdn.net/20170328103038977)
![](http://img.blog.csdn.net/20170328103048899)
1、网络模块,采用的okhttp3+retrofit2封装,是在henlin封装的基础上二次封装,缓存+生命周期。由于是请求不同的Api地址,所以有两个ApiService
github地址:https://github.com/Ahuanghaifeng
欢迎下载使用和star
项目已在应用宝上线:地址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
相关文章推荐
- 为软件质量保驾—过程管理与项目管理技术的应用
- 微信小程序从入门到项目实战
- 没头没尾--项目开发笔记:分模块开发!!?? 分层开发!!??
- 没头没尾--项目开发笔记:UML,IDEF在我们项目中的失败应用
- 没头没尾--项目开发笔记:面向业务的用户界面与面向对象的数据库如何连接
- 没头没尾之项目开发笔记:回忆
- 没头没尾--项目开发笔记 C#企业级模板理解
- 没头没尾--项目开发笔记:C#分布式工程的修改版本
- 使用Log4j为项目配置日志输出应用详解以及示例演示的实现分析
- 金融应用项目的过程改进
- 存储数据键和项目对的类(Dictionary对象)
- 一个金融应用项目的总结
- ASP项目中的通用条件查询模块
- ASP项目中的公共翻页模块
- 在XSL中实现项目列表的例子
- 在WEB项目中多维下拉菜单的实现技巧和方法
- ASP消息服务项目建议书
- 采用XP方法使软件项目获得更大成功
- 项目管理学科发展的特点和趋势
- 项目成功的12个关键原则