1. ホーム
  2. Android

Android用ニュースアプリの簡単な実装です。

2022-02-17 05:24:55

1. レコードを更新する。

2021/11/14.

1. データソースapiを更新し、集計データニュースapiを使用するようにしました。

2. テキストビューグループをTabLayoutに置き換えた。

2021/11/13.

1. Fix the crash of dropdown refresh. 1. updated the api of data source
2. Add a new setting: if the dropdown doesn't get data within 5s, it will stop showing the loading bar.


------------------------------------------------------------------------------------------------------

2. まずエフェクト画像。

                図1 図2

今回のアプリ開発に使用したapiの共有者が記事へのリンクを貼ってくれたことに感謝するとともに、必要な読者はこちらのリンクに移動してください。

リソース|NetEase News用APIを共有する - Jane's Book

集計データapiに差し替えました。 ニュースヘッドライン - ニュースヘッドライン API _APIデータインターフェース_APIインターフェース呼び出し_APIインターフェースプラットフォーム - 集計データ

3. 一般的な考え方の概要

       アプリのインターフェイスは、図1、図2のようにシンプルです。図1の一番上はAndroidネイティブのタイトルバー、図2の一番上は私自身が定義したタイトルバーで、具体的なコードは後述します。図1のタイトルバーの下には5つのパネルを表すTextViewがあり、その下にはFragment+ViewPageのスライドページ、Fragmentの中にはRecyclerviewコントロールが入っています。RecyclerViewのアイテムをクリックすると、図2:使用したapiが対応するコンテンツ情報を返さなかったため、元のURLをWebViewで読み込む必要がありました。実は、画像と対応する情報をクロールするためにJsoupクローラのフレームワークも使ってみましたが、結果はあまり良くありません。それとも、私がJsoupの使い方があまり得意でないのかもしれませんね。

   さて、アプリの全モジュールを説明しましたが、ここで各モジュールの詳細について説明します。

4.APPが使用するオープンソースライブラリ。

  compile 'org.jsoup:jsoup:1.9.2'
    compile 'com.squareup.okhttp3:okhttp:3.4.1'
    compile 'com.android.support:recyclerview-v7:24.2.1'
    compile 'com.android.support:appcompat-v7:24.2.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'com.github.bumptech.glide:glide:3.7.0'
    compile 'com.android.support:cardview-v7:24.2.1'
    compile 'com.yalantis:phoenix:1.2.3'
    compile 'com.android.support:support-v4:24.2.1'

フォニックス このエントリは、私が使用しているドロップダウン・リフレッシュ・オープンソース・コントロールです。

グライド 画像の効率的な読み込みのために。

カードビュー カードのレイアウトです。

okhttp Web通信フレームワーク。

レビュアー  言うまでもないことですが。

メインアクティビティ画面用の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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.thinkpad.wenews.MainActivity">

    <LinearLayout

        android:layout_width="match_parent"
        android:layout_height="wrap_content">
  <TextView
      android:id="@+id/finance"
      android:layout_weight="1"
      android:layout_width="0dp"
      android:text="finance"
      android:gravity="center_horizontal"
      android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/movie"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:text="movie"
            android:gravity="center"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/amusement"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:text="Entertainment"
            android:gravity="center"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/tv"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:text="TV"
            android:gravity="center"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/headline"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:text="headline"
            android:gravity="center"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/newsLive"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:text="News"
            android:gravity="center"
            android:layout_height="wrap_content" />
    </LinearLayout>
    <com.yalantis.phoenix.PullToRefreshView
        android:id="@+id/pull_to_refresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />
</com.yalantis.phoenix.PullToRefreshView>
</LinearLayout>



5. 本プロジェクトのポイント(ViewPager+フラグメント) 実装内容

今回のプロジェクトのキーポイントであるViewPager+fragmentパターンについて。

そこで、ViewPager+Fragmentを使って、上記のような今回のプロジェクトの機能を実現する方法を紹介します。

ビューページャー

ViewPagerは、実は私たちがよく知っているRecyclerViewと似ていて、アダプタ、オブジェクトを格納するListを必要とします。

ViewPagerの基本を学ぶためのリンク付き。 ViewPager詳細(I) --- 基本的な使い方_Android開発ノート - CSDNブログ_Androidのビューページャー

コード

package com.example.thinkpad.wenews;

import android.app.ProgressDialog;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import com.yalantis.phoenix.PullToRefreshView;

import java.util.ArrayList;
import java.util;

public class MainActivity extends AppCompatActivity {

    ViewPager viewPager;


  static List<TextView> tag;
    List<Fragment> viewList;
  static int tagPointer=0;

 static ProgressDialog progressDialog ;
    PullToRefreshView pullToRefreshView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        progressDialog=new ProgressDialog(MainActivity.this);
        progressDialog.setMessage("Loading content... ");
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        pullToRefreshView = (PullToRefreshView) findViewById(R.id.pull_to_refresh);
        viewList = new ArrayList<Fragment>();// Load the View to be paged into the array
       final amusementFragment fragment1 = new amusementFragment();
       final financeFragment fragment2=new financeFragment();
        final armyFragment fragment3=new armyFragment();
      final headlineFragment fragment4=new headlineFragment();
     final tvFragment fragment5=new tvFragment();
      final newsFragment fragment6=new newsFragment();
        viewList.add(fragment2);
        viewList.add(fragment3);
        viewList.add(fragment1);
        viewList.add(fragment5);
        viewList.add(fragment4);
        viewList.add(fragment6);
        FragmentManager fragmentManager=getSupportFragmentManager();
        channelPager pagerAdapter=new channelPager(fragmentManager,viewList,this);
        viewPager.setAdapter(pagerAdapter);
         tag=new ArrayList<>();
        tag.add((TextView)findViewById(R.id.finance));
        tag.add((TextView)findViewById(R.id.movie));
        tag.add((TextView)findViewById(R.id.amusement));
        tag.add((TextView)findViewById(R.id.tv));
        tag.add((TextView)findViewById(R.id.headline));
        tag.add((TextView) findViewById(R.id.newsLive));

       pullToRefreshView.setOnRefreshListener(new PullToRefreshView.OnRefreshListener() {

            public void onRefresh() {
         switch (tagPointer){
                  case 0:
                      GetNews(). fragment1;
                      break;
                  case 1:
                      fragment2.GetNews();
                      break;
                  case 2:
                      fragment3.GetNews();
                      break;
                  case 3:
                      fragment4.GetNews();
                      break;
                  case 4:
                      fragment5.GetNews();
                      break;
                  case 5:
                      Break;
              }
              pullToRefreshView.setRefreshing(false);
            }
        });
    }

}




上記のようなコードで

channelPager pagerAdapter=new channelPager(fragmentManager,viewList,this); is creating my ViewPager adapter

その前に viewList.add(fragment2); を使って、いくつかのフラグメントオブジェクトを viewList に追加しています。

5.1 アダプタクラスchannelPagerからはじめましょう

package com.example.thinkpad.wenews;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util;

List; /**
 * Created by thinkpad on 2019/3/3.
 List; /* */

public class channelPager extends FragmentPagerAdapter {
    List<Fragment> fragmentList=new ArrayList<>();
    MainActivity mContext;
    public channelPager(FragmentManager fm , List<Fragment> list,MainActivity mContext)
    {
        super(fm);
        fragmentList=list;
        this.mContext=mContext;
    }
    @Override
    public Fragment getItem(int position) {
        Log.d("getItem","good");

        return fragmentList.get(position);
    }

    @Override
    public int getCount() {
        return fragmentList!= null ? fragmentList.size() : 0;
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        super.setPrimaryItem(container, position, object);
        MainActivity.tagPointer=position;
        switch (position) {
            case 0: {
                MainActivity.tag.get(0).setBackgroundColor(mContext.getResources().getColor(R.color.colorDark));
                List<TextView> others = new ArrayList<TextView>();
                others.addAll(MainActivity.tag);
                others.remove(0);
                for (TextView textView : others) {
                    textView.setBackgroundColor(mContext.getResources().getColor(R.color.colorWhite));
                }}
            break;
            case 1: {
                MainActivity.tag.get(1).setBackgroundColor(mContext.getResources().getColor(R.color.colorDark));
                List<TextView> others = new ArrayList<TextView>();
                others.addAll(MainActivity.tag);
                others.remove(1);
                for (TextView textView : others) {
                    textView.setBackgroundColor(mContext.getResources().getColor(R.color.colorWhite));
                }

            }
            break;
            case 2: {
                MainActivity.tag.get(2).setBackgroundColor(mContext.getResources().getColor(R.color.colorDark));
                List<TextView> others = new ArrayList<TextView>();
                others.addAll(MainActivity.tag);
                others.remove(2);
                for (TextView textView : others) {
                    textView.setBackgroundColor(mContext.getResources().getColor(R.color.colorWhite));
                }

            }
            break;
            case 3: {
                MainActivity.tag.get(3).setBackgroundColor(mContext.getResources().getColor(R.color.colorDark));
                List<TextView> others = new ArrayList<TextView>();
                others.addAll(MainActivity.tag);
                others.remove(3);
                for (TextView textView : others) {
                    textView.setBackgroundColor(mContext.getResources().getColor(R.color.colorWhite));
                }

            }
            break;
            case 4: {
                MainActivity.tag.get(4).setBackgroundColor(mContext.getResources().getColor(R.color.colorDark));
                List<TextView

このクラスのコンストラクタは、FragmentManager, List<Fragment>, Mainacitivity の3つのパラメータを持っています。

      最初の2つは、super()が親クラスのコンストラクタを呼び出してパラメータfmを渡していることも分かるので必須です。一方、List<Fragment>は言うまでもなく、このクラスでUIを操作する必要があるので、わざわざ渡すのはMainActivityのみとなります。コンストラクタの後には、2つのオーバーロード関数があり、1つ目は固定位置のフラグメントオブジェクトを返し、2つ目は数値を返します。

setPrimaryItemはフラグメントの現在位置を決定するメソッドで、このメソッドで該当部分のTextViewを水色にする機能を実現しています。詳しくはコードをご覧ください。

5.2 以下、フラグメント

package com.example.thinkpad.wenews;

import android.content;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;
import java.util;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

public class amusementFragment extends Fragment {
    private List<NewItem> newItems=new ArrayList<NewItem>();
    private RecyclerView recyclerView_amusement;
    private NewsAdapter adapter;

    public amusementFragment() {
        // Required empty public constructor
    }



    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view =inflater.inflate(R.layout.layout_amusement, container, false);
        recyclerView_amusement=(RecyclerView) view.findViewById(R.id.recyclerview_amusement) ;
        LinearLayoutManager layoutManager=new LinearLayoutManager(getContext());
        recyclerView_amusement.setLayoutManager(layoutManager);
        adapter=new NewsAdapter(newItems);
        recyclerView_amusement.setAdapter(adapter);
GetNews();

        return view;
    }



    public void GetNews(){
    if(!MainActivity.progressDialog.isShowing()){
        MainActivity.progressDialog.show();
    }
    HttpUtil.sendOkhttpRequest("https://3g.163.com/touch/reconstruct/article/list/BA10TA81wangning/0-20.html", new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            Log.d("error11","Get error!!! ");
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            Log.d("Success! ","12121212");
            String text=response.body().string();
            Log.d("response",text);
            char test[]=text.toCharArray();
            for(int i=0;i<9;i++)
                test[i]=' ';
            test[test.length-1]=' ';
            Log.d("text",String.valueOf(test));
            text=String.valueOf(test);
            parseJSONWithJSONObject(text);
        }
    });
}
    private void parseJSONWithJSONObject(String jsonData)
    {
        try{
            Log.d("hello","hello");
            JSONObject jsonObject=new JSONObject(jsonData);

            Log.d("testtest",jsonObject.toString());
            final JSONArray array=jsonObject.getJSONArray("BA10TA81wangning");
            for(int i=1;i<array.length();i++)
            {
                NewItem one=new NewItem();
                JSONObject object=array.getJSONObject(i);

                one.setPictureAddress(object.getString("imgsrc"));
                one.setTitle(object.getString("title"));
                one.setContentAddress(object.getString("url"));
                Log.d("contentadress",one.getContentAddress());
                if(one.getContentAddress().toCharArray()[0]=='0')//filter the useless content address object into
                {
                    Log.d("goodnull","truetrue!+");
                    continue;

                }
                Log.d("title12",one.getTitle());
                Log.d("pic12",one.getPictureAddress());
                boolean check=false;
                for(NewItem c:newItems){
                    if(c.getTitle().equals(one.getTitle()){
                        check=true;
                    break;
                }}
                if(!check)
                newItems.add(one);
            }

            Log.d("listsize","1234"+" " "+newItems.size());
           getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if(MainActivity.progressDialog.isShowing())
                    MainActivity.progressDialog.dismiss();
                    adapter.notifyDataSetChanged();
                }
            });
        }catch (Exception e)
        {
            e.printStackTrace();

        }
    }
}



後で考えてもいいと思うんです。GetNews()は、私がコンテンツを更新するためのメソッドです。コンテンツをロードするための私のモジュールはonCreatView()に配置されているので、実際には、毎回フラグメントは、それが交差する前に更新されますが、これは非常に良い感じではない、あなたがより良い方法を持っている場合は、アドバイスを与えることを躊躇しないしてください。

httpsendrequestは、以下のようにリクエストを開始するメソッドです。


public class HttpUtil {
    private String channel="";
    private final static String apikey="LzQUsyWYuvT5kNqAAuUuY1pBmhhS37V7";

    public static void sendOkhttpRequest(String address,okhttp3.Callback callback){
        // Create RequestBody object to store the parameters to be submitted, the parameters are apikey,text,userid.
        /*RequestBody requestBody=new FormBody.
                .add("key",apikey)
                .add("info",text)
                .add("userid","128")
                .build();*/

        OkHttpClient client =new OkHttpClient();
        Request request =new Request.
                .url(address)
                .build();
        client.newCall(request).enqueue(callback);//enqueue method opens a sub-thread internally and eventually calls back the result to okhttp3.

    }
}


5.3 RecyclerViewのアイテムクラスコード。

public class NewItem {
    private String title;
    private String pictureAddress;
    private String contentAddress;

    public String getContentAddress() {
        return contentAddress;
    }

    public void setContentAddress(String contentAddress) {
        this.contentAddress = contentAddress;
    }

    public String getPictureAddress() {
        return pictureAddress;
    }

    public void setPictureAddress(String pictureAddress) {
        this.pictureAddress = pictureAddress;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}


6 概要とソースコードダウンロードリンク 

基本的にはこれで終わりです。 ソースコードをダウンロードしている間に、「いいね!」やGitHubの「スター」を押していただけると幸いです。

githubプロジェクトのアドレスです。 https://github.com/DhyanaCoder/WeNews/tree/master  ダウンロードだけでなく、自由に閲覧することができます。