Use RecyclerView to realize news list and Activity jump

Keywords: Java Android

Function effect display

Interface design analysis

The above APP interface is divided into two parts. The first part is the news list page and the second part is the news details page. The news list page can be implemented by recyclerView. Here, I use HtmlTextView to accept the html data returned by the url for display. The details are as follows:

News details page

The list is added on the wechat tab page this time, so it can be directly added in the fragment_ Set in the news.xml file

  • Add RecyclerView control
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".news">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
  • Create a layout for recyclerView

For each item, it contains pictures, news headlines, news sources, and release time, so the following layout can be made.

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/liner1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/news_image"
        android:layout_width="140dp"
        android:layout_height="100dp"
        android:layout_weight="0"
        tools:srcCompat="@tools:sample/avatars" />
    <LinearLayout
        android:id="@+id/liner2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="0"
        android:orientation="vertical">
        <TextView
            android:id="@+id/news_title"
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:text="title"
            android:textSize="20sp" />
        <LinearLayout
            android:id="@+id/liner3"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <TextView
                android:id="@+id/news_author"
                android:layout_width="wrap_content"
                android:layout_height="20dp"
                android:textSize="16sp"
                android:layout_weight="1"
                android:text="author" />
            <TextView
                android:id="@+id/news_date"
                android:layout_width="wrap_content"
                android:layout_height="20dp"
                android:textSize="16sp"
                android:layout_weight="1"
                android:text="Release time" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>
  • Effect display

News details page

The news details page is relatively simple, because the data of my details page is composed of HTML data returned by okhttp according to the news url request, so htmlTextView is selected as the control to parse the page.

  • Layout file
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="ContentActivity">
    <org.sufficientlysecure.htmltextview.HtmlTextView
        android:id="@+id/html_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:textAppearance="@android:style/TextAppearance.Small" />
</ScrollView>

Function realization method

Control of RecyclerView

Design of Adapter

  • The main task in the adapter is how to correctly fill the json data from the front end into each control of RecyclerView. Therefore, take the corresponding data out of the list and fill it through the setText method.
public class News_adapter extends RecyclerView.Adapter <News_adapter.ViewHolder> {

    public List<Map<String, Object>> list = new ArrayList<>();
    public Context con;
    private AdapterView.OnItemClickListener onItemClickListener;

    public News_adapter(List<Map<String,Object>> list, Context con) {
        this.con=con;
        this.list=list;
    }
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false);
        ViewHolder viewHolder=new ViewHolder(view);
        return viewHolder;
    }
    @Override
    public void onBindViewHolder(final ViewHolder holder, @SuppressLint("RecyclerView") final int position) {
        String test = list.get(position).get("title").toString();
        holder.recy_title.setText(list.get(position).get("title").toString());
        holder.recy_date.setText(list.get(position).get("date").toString());
        Glide.with(holder.recy_imageView.getContext()).load(list.get(position).get("thumbnail_pic_s")).into(holder.recy_imageView);
        holder.recy_author.setText(list.get(position).get("authors").toString());
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Bundle bundle = new Bundle();
                try {
                    bundle.putCharSequence("url",list.get(position).get("url").toString());
                    Intent intent = new Intent(con, ContentActivity.class);
                    intent.putExtras(bundle);
                    con.startActivity(intent);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    @Override
    public int getItemCount() {
        return list.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder {
        public TextView recy_title;
        public ImageView recy_imageView;
        public TextView recy_author;
        public TextView recy_date;
        public ViewHolder(View itemView) {
            super(itemView);
            recy_title = itemView.findViewById(R.id.news_title);
            recy_imageView = itemView.findViewById(R.id.news_image);
            recy_author = itemView.findViewById(R.id.news_author);
            recy_date = itemView.findViewById(R.id.news_date);
        }
    }
    public interface OnItemClickListener{
        void onItemClick(int position);
    }
    //Click method
    public void setOnItemClickListener(OnItemClickListener onItemClickListener){
        this.onItemClickListener = (AdapterView.OnItemClickListener) onItemClickListener;
    }
}

Analysis of data and use of Adapter

  • Data analysis

This time, I used the API of the aggregate news network to return the corresponding json data and parse it in news.java

  • data processing
//okhttp get data
private void okhttpDate() {
        Log.i("okk", "--ok-");
        new Thread(new Runnable() {
            @Override
            public void run() {
                OkHttpClient client = new OkHttpClient();
                Request request = new Request.Builder().url(URL).build();
                try {
                    Response sponse = client.newCall(request).execute();
                    data = sponse.body().string();
                    //analysis
                    jsonJXDate(data);
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }).start();

    }
   //Parse the returned json data and rewrite the list
private void jsonJXDate(String date) {
        if(date!=null) {
            try {
                JSONObject jsonObject = new JSONObject(date);
                //Transfer object
                JSONObject jsonObject1 = jsonObject.getJSONObject("result");
                //Object to array for traversal
                JSONArray jsonArray = jsonObject1.getJSONArray("data");
                //Traversal array
                for (int i = 0; i < jsonArray.length(); i++) {
                    //Traverse and transform the value of the field
                    String title = jsonArray.getJSONObject(i).getString("title");
                    String url = jsonArray.getJSONObject(i).getString("url");
                    String news_date = jsonArray.getJSONObject(i).getString("date");
                    String news_author = jsonArray.getJSONObject(i).getString("author_name");
                    String thumbnail_pic_s = jsonArray.getJSONObject(i).getString("thumbnail_pic_s");
					//Put it into the collection. Do the following operations as needed
                    Map<String, Object> map = new HashMap<>();
                    map.put("title", title);
                    map.put("url", url);
                    map.put("date", news_date);
                    map.put("authors",news_author);
                    map.put("thumbnail_pic_s",thumbnail_pic_s);
                    news_list.add(map);
                }
                Message msg=new Message();
                msg.what=1;
                handler.sendMessage(msg);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
    //Define handler
    public Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 1:
                    //Add split line
                    recyclerview.addItemDecoration(new DividerItemDecoration(
                            context, DividerItemDecoration.VERTICAL));
                    News_adapter recy=new News_adapter(news_list,context);
                    //Format layout display
                    recyclerview.setLayoutManager(new LinearLayoutManager(context));
                    recyclerview.setAdapter(recy);
                    break;


            }
        }
    };

  • Open network permissions
 <uses-permission android:name="android.permission.INTERNET" />
  • Android stipulates that time-consuming operations such as network requests cannot be performed in the main thread, so time-consuming operations need to be performed in the sub thread, and then submit the request to let the main thread update the UI. Therefore, handler is introduced. Handler is the core class for processing asynchronous messages in SDK. It mainly accepts the data sent by the sub thread and uses this data to update the UI with the main thread.
  • Fill the obtained data into the list through the Handler, and map the object created through the Adapter to each control.

Jump of Activity

Content here_ Activity is relatively simple, showing only the code

public class ContentActivity extends AppCompatActivity {
    protected String response = null;
    private String url = null;
    protected HtmlTextView htmlTextView;
    Handler handler = new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what==12)
            {
                htmlTextView.setHtml(response, new HtmlHttpImageGetter(htmlTextView));
            }
        }
    };
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_content);
        htmlTextView = findViewById(R.id.html_text);
        final Intent intent = getIntent();
        Bundle bundle = intent.getExtras();
        url = bundle.getCharSequence("url").toString();
        getHTML(url);
        //html content conversion
    }
    public void getHTML(String aUrl){
        new Thread(new Runnable() {
            @Override
            public void run() {
                OkHttpClient client = new OkHttpClient();
                Request request = new Request.Builder().url(aUrl).build();
                try {
                    Response sponse = client.newCall(request).execute();
                    response = sponse.body().string();
                    Message msg=new Message();
                    msg.what=12;
                    handler.sendMessage(msg);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}
  • To jump from the news list page to the news details page, first listen to the click action.
public interface OnItemClickListener{
        void onItemClick(int position);
    }
    //Click method
    public void setOnItemClickListener(OnItemClickListener onItemClickListener){
        this.onItemClickListener = (AdapterView.OnItemClickListener) onItemClickListener;
    }

  • Then implement the jump. Here, use the class name to jump. You need to register in AndroidManifest.xml
<activity android:name=".ContentActivity"/>
holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Bundle bundle = new Bundle();
                try {
                    bundle.putCharSequence("url",list.get(position).get("url").toString());
                    Intent intent = new Intent(con, ContentActivity.class);
                    intent.putExtras(bundle);
                    con.startActivity(intent);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

Problems encountered and Solutions

Data analysis problem

  • Starting from Android 4.0, Android does not allow network requests in the main thread and UI updates in sub threads. But how can the latest data obtained from the server in the sub thread be passed to the main thread to update the UI? This requires the Handler mechanism.
  • If the thread asynchronously requests the network directly, there will be no updated data in the final list.

News details page data problem

  • The news details returned from the aggregate news API only have the corresponding URL. Therefore, when clicking, you need to request the resources corresponding to the URL and parse and render. Here, you can use the same method as above, use okhttp to initiate the request, accept the returned data, and asynchronously fill in the HtmlTextView control
public void getHTML(String aUrl){
        new Thread(new Runnable() {
            @Override
            public void run() {
                OkHttpClient client = new OkHttpClient();
                Request request = new Request.Builder().url(aUrl).build();
                try {
                    Response sponse = client.newCall(request).execute();
                    response = sponse.body().string();
                    Message msg=new Message();
                    msg.what=12;
                    handler.sendMessage(msg);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        
 Handler handler = new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what==12)
            {
                htmlTextView.setHtml(response, new HtmlHttpImageGetter(htmlTextView));
            }
        }
    };
  • Unresolved issues
    In the returned HTML page, the address of the picture is: src=//dfzximg01.dftoutiao.com/news /... png, which makes the control unable to parse the picture, that is, the content of the first presentation part of the article appears, with only text and no picture.

Code warehouse address

gitee warehouse address

Posted by Spoiler on Sun, 24 Oct 2021 03:56:30 -0700