首先来看一下效果图,以下就是我设想要做的事。
本次实验目标概述:
1、编写一个json文件里面存放学生的信息,该源将模拟从Internet加载json数据,然后填充到列表项中。
2、当应用程序模拟获取网络数据的时候,列表才会在底部显示加载视图。
3、我们将从Internet中用URL加载图形并将其设置到视图显示中,这里使用了Glide库。
4、json数据将会在应用程序中不断给予学生信息,形成无限列表。
本实验基于安卓PlaceHolderView库,该库具有InfinitePlaceHolderView类能够帮助实现本次设想。
在android studio中设立一个新项目。
在*build.gradle
中*添加依赖项。
android {
...
sourceSets {
main {
assets.srcDirs = ['src/main/assets', 'src/main/assets/']
res.srcDirs = ['src/main/res', 'src/main/res/drawable']
}
}
}
dependencies {
...
compile 'com.mindorks:placeholderview:0.7.1'
compile 'com.android.support:cardview-v7:25.3.1'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.google.code.gson:gson:2.7'
}
在src/main目录中创建一个文件夹assets,用来存放json文件(内有学生信息),
在 mainfests中的AndroidManifest.xml
中添加Internet权限,没有该权限不能访问因特网。
< users-permission android :name = “ android.permission.INTERNET ” />
加在
的后面即可。
什么是JSON:JSON即JavaScript Object Natation, 它是一种轻量级的数据交换格式, 与XML一样, 是广泛被采用的客户端和服务端交互的解决方案.
src/layout/activity_main.xml
该xml定义了列表的布局,设置列表的布局的整体方向为垂直方向。
src/layout/load_more_item_view.xml
该xml定义了列表的每一项的布局。
列表项的布局大致长这样:最上面的是学生名字,中间的是图片,正下方是学生信息,右下角是年级。
src/layout/load_more_view.xml
该xml是加载界面布,当从json中获取数据时,显示加载图标。
布局大致长这样:
infinite_list.json
文件放入步骤1中创建的assets文件夹中并写入学生信息。name
是学生姓名,image_url
是图片地址,caption
是学生的信息,grade
是年级信息。
以json形式放置种子文件非常容易解析为模型。
[
{
"name" : "吴家鹏",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"caption" : "福建师范大学数学与信息学院学生,学号116072017032",
"grade" : "2017级"
},
{
"name" : "陈彬",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"caption" : "福建师范大学法学院学生,学号116072017031",
"grade" : "2017级"
},
{
"name" : "赵文鑫",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"caption" : "福建师范大学化学院学生,学号116072017001",
"grade" : "2018级"
},
{
"name" : "王文忠",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"name" : "福建师范大学生命科学学院学生,学号116072017040",
"grade" : "2016级"
},
{
"name" : "张瑞建",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"caption" : "福建师范大学法学院研究生,学号116072017030",
"grade" : "2014级"
},
{
"name" : "闫少奇",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"caption" : "福建师范大学法学院研究生,学号116072017022",
"grade" : "2015级"
},
{
"name" : "张少",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"caption" : "福建师范大学生命科学学院学生,学号116072017040",
"grade" : "2018级"
},
{
"name" : "何文",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"caption" : "福建师范大学网络学院学生,学号116072017040",
"grade" : "2018级"
},
{
"name" : "杨子琪",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"caption" : "福建师范大学文学院学生,学号116072017040",
"grade" : "2018级"
},
{
"name" : "陈晨",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"caption" : "福建师范大学教育学生,学号116072017040",
"grade" : "2017级"
},
{
"name" : "杨超",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"caption" : "福建师范大学音乐学院学生,学号116072017040",
"grade" : "2018级"
},
{
"name" : "林志强",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"caption" : "福建师范大学生命科学学院学生,学号116072017040",
"grade": "2018级"
},
{
"name" : "叶存浩",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"caption" : "福建师范大学物理学院学生,学号116072017040",
"grade" : "2018级"
},
{
"name": "林振铭",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"caption" : "福建师范大学音乐学院学生,学号116072017040",
"grade" : "2018级"
},
{
"name" : "林腾翔",
"image_url" : "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=11813822,2468845429&fm=26&gp=0.jpg",
"name" : "福建师范大学文学院学生,学号116072017040",
"grade" : "2018级"
}
]
其实JSON数据就是一段字符串,只不过有不同意义的分隔符将其分割开来而已,其中
[] 代表的是一个数组;
{} 代表的是一个对象;
“ ” 表示的是属性值;
:代表的是前后之间的关系,冒号前面是属性的名称,后面是属性的值,这个值可以是基本数据类型,也可以是引用数据类型。
utils.java
包含解析种子json文件填充模型所需的方法InfiniteFeedInfo.java
public class Utils {
private static final String TAG = "Utils";
public static List loadInfiniteFeeds(Context context){
try{
GsonBuilder builder = new GsonBuilder();
Gson gson = builder.create();
JSONArray array = new JSONArray(loadJSONFromAsset(context, "infinite_news.json"));
List feedList = new ArrayList<>();
for(int i=0;i
如果要将一个json数据转换为对象的话需要使用fromJson(String json, Class classOfT) /fromJson(String json, Type typeOfT)
,当我们将对象转换为String的时候根据String toJson(Object src)
方法。这里需要注意一点,如果response.body().string()
调用大于一次的话,就会报错java.lang.IllegalStateException: closed,因为response.body().string()
调用一次之后流就断掉了,需要重新构建一个response。
InfiniteFeedInfo.java
public class InfiniteFeedInfo {
@SerializedName("name")
@Expose
private String name;
@SerializedName("image_url")
@Expose
private String imageUrl;
@SerializedName("caption")
@Expose
private String caption;
@SerializedName("grade")
@Expose
private String grade;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getCaption() {
return caption;
}
public void setCaption(String caption) {
this.caption = caption;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
}
1、首先说一下SerializedName的主要作用:属性重命名,可以将json中的属性名转为我们自己自定义的属性名其次@SerializedName
注解提供了两个属性,上面用到了其中一个’value’,别外还有一个属性’alternate’:接收一个String数组,alternate数组中出现任意一个属性名都可以转换为自定义的属性,如果出现多个则以最后一个为准。@SerializedName
注解属于gson类,读取json文件变量并将其绑定到模型变量。
2、@Expose
用于使变量对于gson的解析变为可读。
ItemView.java
自定义生成JavaBean。
@Layout(R.layout.load_more_item_view)
public class ItemView {
@View(R.id.nameTxt)
private TextView nameTxt;
@View(R.id.captionTxt)
private TextView captionTxt;
@View(R.id.gradeTxt)
private TextView gradeTxt;
@View(R.id.imageView)
private ImageView imageView;
private InfiniteFeedInfo mInfo;
private Context mContext;
public ItemView(Context context, InfiniteFeedInfo info) {
mContext = context;
mInfo = info;
}
@Resolve
private void onResolved() {
nameTxt.setText(mInfo.getName());
captionTxt.setText(mInfo.getCaption());
gradeTxt.setText(mInfo.getGrade());
Glide.with(mContext).load(mInfo.getImageUrl()).into(imageView);
}
}
笔记:
@layout
用于将xml布局与此类绑定。
@View
用于将视图绑定到我们要引用的布局中。
@Resolve
当视图位于内存中时调用一个方法,以便用数据填充该视图。
Glide
用法传承目前流行的链式调用,他的基础用法如下。
/**
* 基础用法.
*/
private void baseUsed(){
Glide.with(this)
.load(URL)
.into(mImageView);
}
创建LoadMoreView.java
类,为了模拟从Internet延迟加载数据,我定义了ForcedWaitedLoading
类。此类创建一个新线程,然后在2秒后,在UI线程中添加更多数据视图列表,该视图应始终从UI线程更新。
@Layout(R.layout.load_more_view)
public class LoadMoreView {
public static final int LOAD_VIEW_SET_COUNT = 6;
private InfinitePlaceHolderView mLoadMoreView;
private List mFeedList;
public LoadMoreView(InfinitePlaceHolderView loadMoreView, List feedList) {
this.mLoadMoreView = loadMoreView;
this.mFeedList = feedList;
}
@LoadMore
private void onLoadMore(){
Log.d("DEBUG", "onLoadMore");
new ForcedWaitedLoading();
}
class ForcedWaitedLoading implements Runnable{
public ForcedWaitedLoading() {
new Thread(this).start();
}
@Override
public void run() {
try {
Thread.currentThread().sleep(2000);
}catch (InterruptedException e){
e.printStackTrace();
}
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
int count = mLoadMoreView.getViewCount();
Log.d("DEBUG", "count " + count);
for (int i = count - 1;
i < (count - 1 + LoadMoreView.LOAD_VIEW_SET_COUNT) && mFeedList.size() > i;
i++) {
mLoadMoreView.addView(new ItemView(mLoadMoreView.getContext(), mFeedList.get(i)));
if(i == mFeedList.size() - 1){
mLoadMoreView.noMoreToLoad();
break;
}
}
mLoadMoreView.loadingDone();
}
});
}
}
}
@LoadMore
当列表滚动到最后一项时,将调用此注释。任何获取更多数据的请求都会调用此带注释的方法。mLoadMoreView.loadingDone()
当所有数据都已获取并且视图已填充新数据时,需要调用此方法。它将删除加载视图。mLoadMoreView.noMoreToLoad()
提取数据后,应调用此方法。它将停用加载功能。MainActivity.java
我们获取的实例使用InfiniteFeedInfo
模型列表中的数据添加视图。
使用setLoadMoreResolver
方法添加LoadMoreView
要用作加载指示符的对象。
public class MainActivity extends AppCompatActivity {
private InfinitePlaceHolderView mLoadMoreView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLoadMoreView = (InfinitePlaceHolderView)findViewById(R.id.loadMoreView);
setupView();
}
private void setupView(){
List feedList = Utils.loadInfiniteFeeds(this.getApplicationContext());
Log.d("DEBUG", "LoadMoreView.LOAD_VIEW_SET_COUNT " + LoadMoreView.LOAD_VIEW_SET_COUNT);
for(int i = 0; i < LoadMoreView.LOAD_VIEW_SET_COUNT; i++){
mLoadMoreView.addView(new ItemView(this.getApplicationContext(), feedList.get(i)));
}
mLoadMoreView.setLoadMoreResolver(new LoadMoreView(mLoadMoreView, feedList));
}
}
PlaceHolderView库介绍文献:https://janishar.com/PlaceHolderView/docs/introduction.html
json数据解析:https://www.open-open.com/bbs/view/1319448346593
网络图片获取:https://blog.csdn.net/qq_42777804/article/details/103515640