# 一个小时打造新闻 app
# 前言
作为一个新手,学完基础总想做点什么东西出来。于是我试着去模仿那些优秀的开源作品。
模仿作品:[LookLook 开源项目](https://github.com/xinghongfei/LookLook)
经过一些波折和学习,写下模仿过程。
## 一个小时打造新闻 app
实际上我花了大概三天才弄懂所有的东西,不过有了经验确实可以在一个小时里完成。
# 使用框架:
rxjava 和 retrofit 以及一个开源扩展的 recyclerview 和注解框架 butterknife
集体依赖如下:
```
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.android.support:design:24.2.1'
testCompile 'junit:junit:4.12'
//依赖注解
//依赖添加
compile 'com.jakewharton:butterknife:8.4.0'
apt 'com.jakewharton:butterknife-compiler:8.4.0'
compile 'com.google.code.gson:gson:2.7'
//高级的recyclerview
compile 'com.jude:easyrecyclerview:4.2.3'
compile 'com.android.support:recyclerview-v7:24.2.0'
//rxjava
compile 'com.squareup.retrofit2:retrofit-converters:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'io.reactivex:rxandroid:1.2.1'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-scalars:2.1.0'
compile 'com.github.bumptech.glide:glide:3.7.0'
}
```
# 开始制作 app
## 界面制作:
新建项目,选择模板----> 调整模板
![](https://www.writebug.com/myres/static/uploads/2021/11/17/03ef6c1d098c00adb4f1922fed279b87.writebug)
### 菜单调整
可以看到有 menu 里面两个文件
一个是主菜单,显示在 Toobar 上面
另一个是抽屉的菜单,按需修改即可。
`activity_main_drawer.xml`
```
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="@+id/nav_camera"
android:icon="@drawable/ic_menu_slideshow"
android:title="新闻精选" />
<item
android:id="@+id/nav_gallery"
android:icon="@drawable/ic_face_black_24dp"
android:title="轻松一刻" />
<item
android:id="@+id/nav_slideshow"
android:icon="@drawable/ic_menu_gallery"
android:title="每日美图" />
<item
android:id="@+id/nav_manage"
android:icon="@drawable/ic_menu_manage"
android:title="应用推荐" />
</group>
<item android:title="其他">
<menu>
<item
android:id="@+id/nav_share"
android:icon="@drawable/ic_menu_share"
android:title="软件分享" />
<item
android:id="@+id/nav_send"
android:icon="@drawable/ic_menu_send"
android:title="软件关于" />
</menu>
</item>
</menu>
```
抽屉除了 menu 还有上面一部分,可以设置头像和签名。
`nav_header_main.xml`
```
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar"
android:gravity="bottom"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:orientation="vertical">
<ImageView
android:layout_gravity="center"
android:id="@+id/imageView"
android:layout_width="100dp"
android:layout_height="100dp"
app:srcCompat="@drawable/ic_app_icon" />
<TextView
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="一日之计在于晨,一年之计在于春。"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
<TextView
android:gravity="center"
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="1458476478@qq.com" />
</LinearLayout>
```
主界面大概这就可以了,剩下的就是要动态添加 fragement 到 FragLayout 里面去。
## 数据获取
#### 首先新建 fragment_news,布局文件只需要一个 `EasyRecyclerView` 即可
添加依赖
```
//高级的recyclerview
compile 'com.jude:easyrecyclerview:4.2.3'
compile 'com.android.support:recyclerview-v7:24.2.0'
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.jude.easyrecyclerview.EasyRecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:recyclerClipToPadding="true"
app:recyclerPadding="8dp"
app:recyclerPaddingBottom="8dp"
app:recyclerPaddingLeft="8dp"
app:recyclerPaddingRight="8dp"
app:recyclerPaddingTop="8dp"
app:scrollbarStyle="insideOverlay"
app:scrollbars="none" />
</LinearLayout>
```
### 使用 rxjava 和 retrofit 获取 JSON 数据
我的数据来自[天性数据](http://www.tianapi.com/),只需要注册即可获得 APIKEY。
数据请求核心代码:
#### 创建 retrofit 的请求接口
```
public interface ApiService{
@GET("social/")
Observable <NewsGson> getNewsData(@Query("key")String key,@Query("num") String num,@Query("page") int page);
```
注意返回的是 Gson 数据而且设置为"被观察者"
数据获取函数:
```
private void getData() {
Log.d("page", page + "");
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://api.tianapi.com/")
//String
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())//添加 json 转换器
// compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())//添加 RxJava 适配器
.build();
ApiService apiManager = retrofit.create(ApiService.class);//这里采用的是Java的动态代理模式
apiManager.getNewsData("你的APIKREY", "10", page)
.subscribeOn(Schedulers.io())
.map(new Func1<NewsGson, List<News>>() {
@Override
public List<News> call(NewsGson newsgson) { //
List<News> newsList = new ArrayList<News>();
for (NewsGson.NewslistBean newslistBean : newsgson.getNewslist()) {
News new1 = new News();
new1.setTitle(newslistBean.getTitle());
new1.setCtime(newslistBean.getCtime());
new1.setDescription(newslistBean.getDescription());
new1.setPicUrl(newslistBean.getPicUrl());
new1.setUrl(newslistBean.getUrl());
newsList.add(new1);
}
return newsList; // 返回类型
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber