手把手教!如何通过API获取数据并放入RecyclerView列表中展示

代码不全,但尽可能详细的讲解了主要实现步骤,希望能对各位看官有所帮助!

步骤:

一、准备一个RecyclerView列表用于展示数据

二、找到对应的API接口并根据Json格式构造用于解析的Gson类

三、创建ViewModel类承担数据操作的责任

四、将解析好的数据放入RecyclerView中

一、准备一个RecyclerView列表用于展示数据

  1. 在闭包中加入相应的依赖库
implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation "androidx.recyclerview:recyclerview-selection:1.1.0-rc03"
  1. 在对应的xml文件中加入RecyclerView控件

    
    
  2. 为列表中的子项创建一个xml布局页面,再建立一个类存放展示所需的字段

  3. 接下来要为RecyclerView准备一个适配器,新建NewAdapter类继承自RecyclerView.Adapter,重写和加载参数相关的方法,onCreateViewHolder()、onBindViewHolder ()和getItemCount()这三个方法。NewAdapter的泛型数据类型是自定义的ViewHolder。NewAdapter中有一个构造函数,把要展示的数据源传进来,并赋值给一个全局变量,作为数据源。后续操作都在数据源的基础上进行。


  4. onCreateViewHolder()用于创建ViewHolder实例。加载news_item布局,创建ViewHolder实例,并把加载出来的布局传入到构造函数中,最后将ViewHolder的实例返回。

    public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
        //加载item布局
        final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.new_item, parent, false);
        //创建ViewHolder实例
        final ViewHolder holder = new ViewHolder(view);
        //未来:实现下面两个页面跳转到仓库主页的activity
        holder.newView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                News news= newsList.get(position);
                Toast.makeText(v.getContext(), "you will see repo ", Toast.LENGTH_SHORT).show();
            }
        });
       //未来:实现下面两个点击事件跳转到个人主页的activity
        holder.userImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                News news= newsList.get(position);
                Toast.makeText(v.getContext(), "you will see profile of  " + news.getUserName(), Toast.LENGTH_SHORT).show();
            }
        });
        holder.userName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                News news= newsList.get(position);
                Toast.makeText(v.getContext(), "you will see profile of  " + news.getUserName(), Toast.LENGTH_SHORT).show();
            }
        });
        return holder;
    }
    
  5. onBindViewHolder ()用于对RecyclerView子项的数据进行赋值。我们通过position参数得到当前项的News实例。

    public void onBindViewHolder(final ViewHolder holder, int position) {
        final News news = newsList.get(position);
        holder.userName.setText(news.getUserName());
        holder.time.setText(news.getTime());
        holder.action.setText(news.getAction());
    }
    
  6. getItemCount()统计子项个数,返回数据源的长度。

    public int getItemCount() {
        return newsList.size();
    }
    

二、找到对应的API接口并根据Json格式构造用于解析的Gson类

  1. 通过GraphQL找到想找的API,复制到postman里生成请求代码。获取到的请求代码我把它放到了一个函数里,以便调用和修改。

    public static String getUserNews() {
        return "{\"query\":\"query MyQuery {\\r\\n  viewer {\\r\\n    following(first: 10) {\\r\\n      edges {\\r\\n        node {\\r\\n          avatarUrl(size: 10)\\r\\n          login\\r\\n          starredRepositories {\\r\\n            edges {\\r\\n              starredAt\\r\\n            }\\r\\n            nodes {\\r\\n              nameWithOwner\\r\\n            }\\r\\n          }\\r\\n        }\\r\\n      }\\r\\n    }\\r\\n  }\\r\\n}\",\"variables\":{}}";
    }
    
  2. 通过OkHttp发起HTTP请求,建立网络连接

    • 发起HTTP请求,需要创建一个Request对象。可以在最终的bulid方法前连缀很多方法来丰富Request对象,比如指定服务器返回数据格式为json,将上一步得到的请求代码放入body中。

    • 调用OkHttpClient的newCall(request)来创建一个call对象,重写onFailure和onResponse方法。

      //构造请求
      Request.Builder builder = BaseRequestBuilder.getBuilder();
      MediaType mediaType = MediaType.parse("application/json");
      //Json代码
      RequestBody body = RequestBody.create(mediaType, RequestBodyHelper.getUserNews());
      //构建请求
      Request request = builder.method("POST", body).build();
      OkHttpClient client = OkhttpUtil.getInstance();
      //请求数据
      client.newCall(request).enqueue(new Callback() {
          @Override
          public void onFailure(@NotNull Call call, @NotNull IOException e) {
              doFailure();
          }
      
          @Override
          public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
              Log.d("tag", "List数组创建成功");
              doSuccess(response);
      
          }
      });
      //服务器返回的数据
      String data = response.body().string();
      
  3. 通过Gson方法解析服务器返回的JSON数据

    • 先在闭包中添加依赖项

      implementation 'com.google.code.gson:gson:2.8.6'
      
    • 再用Gson反序列化服务器返回的数据。我获取的数据是一个List数组。先对返回来的数据进行字符串处理,确保待解析的字符串是完整的[XXXXXX]。这里说明一下,{}代表里面的代码块是一个类,[]代表里面的代码块是一个数组。根据在GraphQL中看到的Json格式,从内往外的去定义相应的类和数组,层层嵌套,确保变量命名和Json数据中名字一致。这里用简单的例子举例说明一下吧。

      //String data = response.body().string();服务器返回的数据
      String userJson = " [{'isDeveloper':false,'name':'xiaoqiang','age':26,'email':'[email protected]'}, {'isDeveloper':true,'name':'xiaoqiang123','age':27,'email':'[email protected]' }]";
      
      Gson gson = new Gson();
       Type userListType = new TypeToken>(){}.getType();
      
      List userList = gson.fromJson(userJson, userListType);
      //这个List将为后续操作的数据源
      
    • 对于 List ,反序列化时必须提供它的Type,通过 Gson 提供的 TypeToken.getType() 方法可以定 义当前List的 Type 。这个Type应为服务器返回数据的最外层所定义的类。

三、创建ViewModel类承担数据操作的责任

ViewModel的生命周期比Activity和Fragment都要长,用ViewModel存储数据不用担心数据保存和恢复的问题。再者UI controller 比如 Activity 、Fragment 是设计用来渲染展示数据、响应用户行为、处理系统的某些交互。如果再要求他去负责加载网络或数据库数据,会让其显得臃肿和难以管理。所以为了简洁、清爽、 丝滑,我们可以分离出数据操作的职责给 ViewModel。下面来看看怎么用ViewModel管理数据。

  1. 创建一个NewsViewModel继承自ViewModel,并在构造函数中初始化了数据源,虽然Google为防止内存泄漏禁止在 ViewModel 中持有 Context 或 activity 或 view 的引用,但是为了在ViewModel里操作UI线程,我从外部传了个Context进来。

         private MutableLiveData> Listdata;
        List newList = new ArrayList<>();
        Context newsContext;
    
        public NewsViewModel() {
            Listdata = new MutableLiveData<>();
            initNewList();
        }
    
        public LiveData> getList() {
            return Listdata;
        }
        private void initNewList(){//上文通过API获取数据源,在doSuccess中完成了数据解析,并调用了setListValue()将数据装入ViewModel的Listdata中
        }
         public void setContext(Context context) {
            newsContext = context;
        }
         public void setListValue() {
            ((MainActivity) newsContext).runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Listdata.setValue((ArrayList) newList);
                }
            });
        }
    
  2. 在UI控制器里(Fragment或Activity)生成一个ViewModel对象。通过对象调用getList()就可以获取数据源进行操作了。

    newsViewModel= new ViewModelProvider(this).get(NewsViewModel.class);
    

四、将解析好的数据放入RecyclerView中

  1. 先把RecyclerView与布局页绑定(我的RecyclerView是放在fragment里的)

    View root = inflater.inflate(R.layout.fragment_news, container, false);
    final RecyclerView newsRecyclView = root.findViewById(R.id.news_recyc);
    LinearLayoutManager layoutManager = new LinearLayoutManager(this.getActivity());
    newsRecyclView.setLayoutManager(layoutManager);
    
  2. 之前已经加载了item的布局页到适配器中,因此需要将适配器与newsRecyclView进行绑定

    //ViewModel里用于刷新UI的观察者,getList()获取到数据后则在这个方法中显示在UI上
    newsViewModel.getList().observe(getViewLifecycleOwner(), new Observer>() {
                @Override
                public void onChanged(@Nullable ArrayList s) {
                  //将数据传入适配器,将适配器绑定到RecyclerView
                    NewAdapter adapter=new NewAdapter(s);
                    newsRecyclView.setAdapter(adapter);
                  //负责页面刷新效果的代码
                    progressBar.setVisibility(View.GONE);
                    newsRecyclView.setVisibility(View.VISIBLE);
                }
            });
    

你可能感兴趣的:(手把手教!如何通过API获取数据并放入RecyclerView列表中展示)