主要是借鉴了https://blog.csdn.net/jky_yihuangxing/article/details/133869285,博主写的更详细,我就是主要记录一下实现过程
1.聚合数据获取api和key
点击进去选择接口文档可以看到接口地址,请求方式等
进入聚合数据→选择API→选择想要获取的数据,示例选取的是免费的新闻头条
在个人中心→数据中心→我的API中,可以查看到key
在知道接口地址和key时,API接口的准备工作已完成
我们可以先看看Json返回数据,这里只拼接一了个请求参数key,也是必须的,其他参数按需添加
2.EasyHttp获取数据
1)activity_news.xml
是打算做一个新闻获取的列表,所以先写一个recycleview,也可以使用listview
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/news_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
2)items_news.xml
现在写recycleview里面的具体内容,从聚合数据的那个接口文档可以知道返回的参数,我这里把所有参数都写出来了,也可以适当减少
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.lancer.lanui.widget.image.LanImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:id="@+id/newsImage"/>
<TextView
android:layout_width="200dp"
android:layout_height="25dp"
android:id="@+id/newsTitle"
android:layout_marginLeft="85dp"/>
<TextView
android:layout_width="200dp"
android:layout_height="25dp"
android:id="@+id/newsAuthor"
android:layout_marginLeft="85dp"
android:layout_marginTop="25dp"/>
<TextView
android:layout_width="200dp"
android:layout_height="25dp"
android:id="@+id/newsTime"
android:layout_marginLeft="85dp"
android:layout_marginTop="50dp"/>
<TextView
android:layout_width="200dp"
android:layout_height="25dp"
android:id="@+id/newsuniquekey"
android:layout_marginTop="80dp"/>
<TextView
android:layout_width="200dp"
android:layout_height="25dp"
android:id="@+id/newscategory"
android:layout_marginTop="105dp"/>
<TextView
android:layout_width="200dp"
android:layout_height="25dp"
android:id="@+id/newsurl"
android:layout_marginTop="130dp"/>
<com.lancer.lanui.widget.image.LanImageView
android:layout_width="200dp"
android:layout_height="25dp"
android:id="@+id/newsthumbnail_pic_s02"
android:layout_marginTop="155dp"/>
<com.lancer.lanui.widget.image.LanImageView
android:layout_width="200dp"
android:layout_height="25dp"
android:id="@+id/newsthumbnail_pic_s03"
android:layout_marginTop="180dp"/>
<TextView
android:layout_width="200dp"
android:layout_height="25dp"
android:id="@+id/newsis_content"
android:layout_marginTop="205dp"/>
</RelativeLayout>
3)NewsApi
初始化实体类,太长了,可以自己按需求添加,只有一个需要注意的地方,借鉴了gihub的EasyHttp里说可以把api类和Bean类写在一起,Bean类就不展示了,按需添加,api类的代码如下:
public class NewsApi implements IRequestApi {
@NonNull
@Override
public String getApi() {
return "/toutiao/index";
}
//传输的参数
private String key;
public NewsApi setKey(String key) {
this.key = key;
return this;
}
传入的getapi只需要return "/toutiao/index",域名和拼接的参数key都放在其他地方显示
聚合数据的新闻头条这个可以添加很多请求参数,我就只添加了必须的参数key
4)NewsAdapter
传入数据,用get方法获得,图片用Glide方法获取,用的不是findviewbyId的方法,用的是viewbinding,但是逻辑差不多
package com.lancer.lanui;
import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
import com.bumptech.glide.Glide;
import com.lancer.base.adapter.BaseAdapter;
import com.lancer.lanui.databinding.ItemNewsBinding;
import java.util.List;
public class NewsAdapter extends BaseAdapter<NewsApi.NewsInfo.ResultDTO.DataDTO, ItemNewsBinding> {
public NewsAdapter(Context context, LifecycleOwner owner, List<NewsApi.NewsInfo.ResultDTO.DataDTO> objectArrayList) {
super(context, owner, objectArrayList);
}
@Override
protected void initAdapter(BaseAdapter<NewsApi.NewsInfo.ResultDTO.DataDTO, ItemNewsBinding>.ViewHolder holder, NewsApi.NewsInfo.ResultDTO.DataDTO dataDTO, int position) {
holder.binding.newsTime.setText(dataDTO.getDate());
holder.binding.newsAuthor.setText(dataDTO.getAuthor_name());
holder.binding.newsTitle.setText(dataDTO.getTitle());
holder.binding.newsuniquekey.setText(dataDTO.getUniquekey());
holder.binding.newscategory.setText(dataDTO.getCategory());
holder.binding.newsisContent.setText(dataDTO.getIs_content());
holder.binding.newscategory.setText(dataDTO.getUrl());
Glide.with(context).load(dataDTO.getThumbnail_pic_s()).into(holder.binding.newsImage);
Glide.with(context).load(dataDTO.getThumbnail_pic_s02()).into(holder.binding.newsthumbnailPicS02);
Glide.with(context).load(dataDTO.getThumbnail_pic_s03()).into(holder.binding.newsthumbnailPicS03);
}
}
5)NewsActivity
private void initHttp() {
// 设置 Json 解析容错监听
GsonFactory.setParseExceptionCallback(new ParseExceptionCallback() {
//设置了Gson解析的容错监听器,用于处理解析异常情况
@Override
public void onParseObjectException(TypeToken<?> typeToken, String fieldName, JsonToken jsonToken) {
handlerGsonParseException("解析对象析异常:" + typeToken + "#" + fieldName + ",后台返回的类型为:" + jsonToken);
}
@Override
public void onParseListItemException(TypeToken<?> typeToken, String fieldName, JsonToken listItemJsonToken) {
handlerGsonParseException("解析 List 异常:" + typeToken + "#" + fieldName + ",后台返回的条目类型为:" + listItemJsonToken);
}
@Override
public void onParseMapItemException(TypeToken<?> typeToken, String fieldName, String mapItemKey, JsonToken mapItemJsonToken) {
handlerGsonParseException("解析 Map 异常:" + typeToken + "#" + fieldName + ",mapItemKey = " + mapItemKey + ",后台返回的条目类型为:" + mapItemJsonToken);
}
private void handlerGsonParseException(String message) {
}
});
//如果是DEBUG就选择Deserver,网络请求框架初始化
IRequestServer server;
if (DEBUG) {
server = new DevServer();
} else {
server = new OnlineServer();
}
//创建OkHttpClient实例
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
//使用EasyConfig初始化网络请求框架
EasyConfig.with(okHttpClient)
// 是否打印日志
//.setLogEnabled(BuildConfig.DEBUG)
// 设置服务器配置(必须设置)
.setServer(server)
// 设置请求处理策略(必须设置)
.setHandler(new RequestHandler(this))
// 设置请求参数拦截器
.setInterceptor(new IRequestInterceptor() {
@Override
public void interceptArguments(@NonNull HttpRequest<?> httpRequest,
@NonNull HttpParams params,
@NonNull HttpHeaders headers) {
headers.put("timestamp", String.valueOf(System.currentTimeMillis()));
}
})
// 设置请求重试次数
.setRetryCount(1)
// 设置请求重试时间
.setRetryTime(2000)
// 添加全局请求头
.addHeader("Authorization", "token")
.into();
}
setParseExceptionCallback里面代码是用来设置Gson解析的容错监听器,用于处理解析异常情况
IRequestServer server中是网络请求框架初始化,其中就需要填写域名了,例如OnlineServer中:
public class OnlineServer implements IRequestServer {
@NonNull
@Override
public String getHost() {
return "https://v.juhe.cn";
}
}
开始通过EsayHttp获取网络json数据
private void initNews() {
EasyHttp.get(this)
.api(new NewsApi().setKey("9a3770088626a12803f73b4e8b2259c6"))
.request(new HttpCallbackProxy<HttpData<List<NewsApi.NewsInfo.ResultDTO.DataDTO>>>(this){
@Override
public void onHttpSuccess(HttpData<List<NewsApi.NewsInfo.ResultDTO.DataDTO>> result) throws JSONException {
runOnUiThread(() -> {
newsAdapter = new NewsAdapter(context,NewsActivity.this,result.getData());
binding.newsList.setAdapter(newsAdapter);
newsAdapter.notifyDataSetChanged();
});
}
@Override
public void onHttpFail(Throwable throwable) {
Log.e("请求",throwable.getMessage());
super.onHttpFail(throwable);
}
});
}
在这里就需要填写参数了,如果前面还拼接了其他参数,就在这里也填上,如果要显示数据就去onHTTpSuccess里面处理,由于写了适配器获取数据了,这里就相应适配器,notifyDataSetChanged是必须填写的。