如何在 Android 中创建新闻应用程序?
网络是 android 开发不可或缺的一部分,尤其是在构建数据驱动的客户端时。主要用于网络连接的Java类是HttpUrlConnection。该类需要手动管理数据解析和请求的异步执行。对于网络操作,我们最好使用一个名为 Fast Android Networking Library 的库,它可以负责发送和解析网络请求。在本文中,我们将逐步介绍构建 android 新闻应用程序的过程。 Fast Android Networking Library 支持所有类型的 HTTP/HTTPS 请求,在我们的应用程序中,我们将使用它
- 执行 GET 请求
- 将来自 Internet 的图像加载到 ImageViews 中
这是应用程序最终的样子:
分步实施
第 1 步:创建一个新项目
要了解如何在 Android Studio 中创建新项目,请参阅如何在 Android Studio 中创建/启动新项目并选择Java作为编程语言。
第二步:添加依赖
选择Gradle Scripts > build.gradle(Module:app)并在依赖项部分添加以下依赖项。
implementation 'com.amitshekhar.android:android-networking:1.0.2'
implementation 'com.amitshekhar.android:jackson-android-networking:1.0.2'
添加依赖项后,通过单击立即同步来同步您的项目。
第三步:添加权限
选择manifests > AndroidManifest.xml并在应用标签上方添加互联网权限。
第 4 步:获取 API 密钥
访问 newsapi 并注册。该密钥将在注册后显示并发送到您的电子邮件收件箱。
第 5 步:创建一个新的空 Activity 并将 WebView 添加到布局中
转到app > Java > 右键单击 > New > Activity > Empty Activity并将其命名为 WebActivity。此活动将显示文章的网页作为活动布局的一部分。将 WebView 添加到activity_web.xml文件。导航到app > res > layout > activity_web.xml并将以下代码添加到该文件。
XML
Java
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebView;
public class WebActivity extends AppCompatActivity {
// setting the TAG for debugging purposes
private static String TAG="WebActivity";
// declaring the webview
private WebView myWebView;
// declaring the url string variable
private String url;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web);
// assigning the views to id's
myWebView = (WebView) findViewById(R.id.webview);
Intent intent = getIntent();
// checking if there is an intent
if(intent!=null){
// retrieving the url in the intent
url = intent.getStringExtra("url_key");
// loading and displaying a
// web page in the activity
myWebView.loadUrl(url);
}
}
@Override
protected void onRestart() {
super.onRestart();
finish();
}
}
XML
XML
Java
public class NewsArticle {
// the properties/attributes
// of the ArticleModel
String author;
String title;
String description;
String url;
String urlToImage;
String publishedAt;
String content;
// ArticleModel empty constructor
public NewsArticle() {
}
// get method : returns the name of the author
public String getAuthor() {
return author;
}
// set method : sets the author
public void setAuthor(String author) {
this.author = author;
}
// get method : returns the title of the article
public String getTitle() {
return title;
}
// set method : sets the title
public void setTitle(String title) {
this.title = title;
}
// get method : returns the description of the article
public String getDescription() {
return description;
}
// set method : sets the description
public void setDescription(String description) {
this.description = description;
}
// get method : returns url of the article
public String getUrl() {
return url;
}
// set method : sets the url of the article
public void setUrl(String url) {
this.url = url;
}
// get method : returns the urlToImage of the article
public String getUrlToImage() {
return urlToImage;
}
// set method : sets the UrlToImage
public void setUrlToImage(String urlToImage) {
this.urlToImage = urlToImage;
}
// get method : returns the date
public String getPublishedAt() {
return publishedAt;
}
// set method : sets the date
public void setPublishedAt(String publishedAt) {
this.publishedAt = publishedAt;
}
// get method : returns the content of the article
public String getContent() {
return content;
}
// set method : sets the title
public void setContent(String content) {
this.content = content;
}
}
Java
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.androidnetworking.widget.ANImageView;
import java.util.ArrayList;
public class ArticleAdapter extends RecyclerView.Adapter {
// setting the TAG for debugging purposes
private static String TAG="ArticleAdapter";
private ArrayList mArrayList;
private Context mContext;
public ArticleAdapter(Context context,ArrayList list){
// initializing the constructor
this.mContext=context;
this.mArrayList=list;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// inflating the layout with the article view (R.layout.article_item)
View view=LayoutInflater.from(mContext).inflate(R.layout.article_item,parent,false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// the parameter position is the index of the current article
// getting the current article from the ArrayList using the position
NewsArticle currentArticle=mArrayList.get(position);
// setting the text of textViews
holder.title.setText(currentArticle.getTitle());
holder.description.setText(currentArticle.getDescription());
// subString(0,10) trims the date to make it short
holder.contributordate.setText(currentArticle.getAuthor()+
" | "+currentArticle.getPublishedAt().substring(0,10));
// Loading image from network into
// Fast Android Networking View ANImageView
holder.image.setDefaultImageResId(R.drawable.ic_launcher_background);
holder.image.setErrorImageResId(R.drawable.ic_launcher_foreground);
holder.image.setImageUrl(currentArticle.getUrlToImage());
// setting the content Description on the Image
holder.image.setContentDescription(currentArticle.getContent());
// handling click event of the article
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// an intent to the WebActivity that display web pages
Intent intent = new Intent(mContext, WebActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("url_key",currentArticle.getUrl());
// starting an Activity to display the page of the article
mContext.startActivity(intent);
}
});
}
@Override
public int getItemCount() {
return mArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
// declaring the views
private TextView title,description,contributordate;
private ANImageView image;
public ViewHolder(@NonNull View itemView) {
super(itemView);
// assigning views to their ids
title=itemView.findViewById(R.id.title_id);
description=itemView.findViewById(R.id.description_id);
image=itemView.findViewById(R.id.image_id);
contributordate=itemView.findViewById(R.id.contributordate_id);
}
}
}
Java
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import com.androidnetworking.AndroidNetworking;
import com.androidnetworking.common.Priority;
import com.androidnetworking.error.ANError;
import com.androidnetworking.interfaces.JSONObjectRequestListener;
import com.jacksonandroidnetworking.JacksonParserFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
// TODO : set the API_KEY variable to your api key
private static String API_KEY="";
// setting the TAG for debugging purposes
private static String TAG="MainActivity";
// declaring the views
private ProgressBar mProgressBar;
private RecyclerView mRecyclerView;
// declaring an ArrayList of articles
private ArrayList mArticleList;
private ArticleAdapter mArticleAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// initializing the Fast Android Networking Library
AndroidNetworking.initialize(getApplicationContext());
// setting the JacksonParserFactory
AndroidNetworking.setParserFactory(new JacksonParserFactory());
// assigning views to their ids
mProgressBar=(ProgressBar)findViewById(R.id.progressbar_id);
mRecyclerView=(RecyclerView)findViewById(R.id.recyclerview_id);
// setting the recyclerview layout manager
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
// initializing the ArrayList of articles
mArticleList=new ArrayList<>();
// calling get_news_from_api()
get_news_from_api();
}
public void get_news_from_api(){
// clearing the articles list before adding news ones
mArticleList.clear();
// Making a GET Request using Fast
// Android Networking Library
// the request returns a JSONObject containing
// news articles from the news api
// or it will return an error
AndroidNetworking.get("https://newsapi.org/v2/top-headlines")
.addQueryParameter("country", "in")
.addQueryParameter("apiKey",API_KEY)
.addHeaders("token", "1234")
.setTag("test")
.setPriority(Priority.LOW)
.build()
.getAsJSONObject(new JSONObjectRequestListener(){
@Override
public void onResponse(JSONObject response) {
// disabling the progress bar
mProgressBar.setVisibility(View.GONE);
// handling the response
try {
// storing the response in a JSONArray
JSONArray articles=response.getJSONArray("articles");
// looping through all the articles
// to access them individually
for (int j=0;j
第 6 步:使用 WebActivity。Java
下面是WebActivity 的代码。Java
Java
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebView;
public class WebActivity extends AppCompatActivity {
// setting the TAG for debugging purposes
private static String TAG="WebActivity";
// declaring the webview
private WebView myWebView;
// declaring the url string variable
private String url;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web);
// assigning the views to id's
myWebView = (WebView) findViewById(R.id.webview);
Intent intent = getIntent();
// checking if there is an intent
if(intent!=null){
// retrieving the url in the intent
url = intent.getStringExtra("url_key");
// loading and displaying a
// web page in the activity
myWebView.loadUrl(url);
}
}
@Override
protected void onRestart() {
super.onRestart();
finish();
}
}
第 7 步:将 RecyclerView 添加到 activity_main.xml 文件
选择app > res > layout > activity_main.xml并将以下代码添加到该文件。 RecyclerView 用于有效地显示数据列表,在我们的例子中,它将显示新闻文章列表。
XML
第 8 步:创建新的自定义布局
导航到文件 > 新建 > XML > 布局 XML 文件并将其命名为 article_item。 article_item.xml文件将用于新闻文章列表中的每一行。下面是article_item.xml文件的代码。
XML
第 9 步:创建 NewsArticle 模型类
导航到应用程序 > Java > 包 > 右键单击包 > 新建 > Java类并将其命名为 NewsArticle。我们创建了这个模型类来存储新闻文章数据,如标题、内容、描述等
在我们的模型类中,主要有三种方法:
- 构造函数:初始化新创建的 NewsArticle 对象
- 获取方法:用于获取属性值
- 设置方法:用于设置属性值
下面是NewsArticle 的代码。 Java文件。
Java
public class NewsArticle {
// the properties/attributes
// of the ArticleModel
String author;
String title;
String description;
String url;
String urlToImage;
String publishedAt;
String content;
// ArticleModel empty constructor
public NewsArticle() {
}
// get method : returns the name of the author
public String getAuthor() {
return author;
}
// set method : sets the author
public void setAuthor(String author) {
this.author = author;
}
// get method : returns the title of the article
public String getTitle() {
return title;
}
// set method : sets the title
public void setTitle(String title) {
this.title = title;
}
// get method : returns the description of the article
public String getDescription() {
return description;
}
// set method : sets the description
public void setDescription(String description) {
this.description = description;
}
// get method : returns url of the article
public String getUrl() {
return url;
}
// set method : sets the url of the article
public void setUrl(String url) {
this.url = url;
}
// get method : returns the urlToImage of the article
public String getUrlToImage() {
return urlToImage;
}
// set method : sets the UrlToImage
public void setUrlToImage(String urlToImage) {
this.urlToImage = urlToImage;
}
// get method : returns the date
public String getPublishedAt() {
return publishedAt;
}
// set method : sets the date
public void setPublishedAt(String publishedAt) {
this.publishedAt = publishedAt;
}
// get method : returns the content of the article
public String getContent() {
return content;
}
// set method : sets the title
public void setContent(String content) {
this.content = content;
}
}
第 10 步:创建一个 ArticleAdapter 类
导航到app > Java > package > 右键单击 package > New > Java Class并将其命名为 ArticleAdapter。 ArticleAdapter 类负责从 NewsArticle 模型中获取数据并将其显示在视图上。适配器将提供对数据项的访问,并负责为数据集中的每篇新闻文章创建一个视图。下面是ArticleAdapter 的代码。 Java文件。
Java
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.androidnetworking.widget.ANImageView;
import java.util.ArrayList;
public class ArticleAdapter extends RecyclerView.Adapter {
// setting the TAG for debugging purposes
private static String TAG="ArticleAdapter";
private ArrayList mArrayList;
private Context mContext;
public ArticleAdapter(Context context,ArrayList list){
// initializing the constructor
this.mContext=context;
this.mArrayList=list;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// inflating the layout with the article view (R.layout.article_item)
View view=LayoutInflater.from(mContext).inflate(R.layout.article_item,parent,false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// the parameter position is the index of the current article
// getting the current article from the ArrayList using the position
NewsArticle currentArticle=mArrayList.get(position);
// setting the text of textViews
holder.title.setText(currentArticle.getTitle());
holder.description.setText(currentArticle.getDescription());
// subString(0,10) trims the date to make it short
holder.contributordate.setText(currentArticle.getAuthor()+
" | "+currentArticle.getPublishedAt().substring(0,10));
// Loading image from network into
// Fast Android Networking View ANImageView
holder.image.setDefaultImageResId(R.drawable.ic_launcher_background);
holder.image.setErrorImageResId(R.drawable.ic_launcher_foreground);
holder.image.setImageUrl(currentArticle.getUrlToImage());
// setting the content Description on the Image
holder.image.setContentDescription(currentArticle.getContent());
// handling click event of the article
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// an intent to the WebActivity that display web pages
Intent intent = new Intent(mContext, WebActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("url_key",currentArticle.getUrl());
// starting an Activity to display the page of the article
mContext.startActivity(intent);
}
});
}
@Override
public int getItemCount() {
return mArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
// declaring the views
private TextView title,description,contributordate;
private ANImageView image;
public ViewHolder(@NonNull View itemView) {
super(itemView);
// assigning views to their ids
title=itemView.findViewById(R.id.title_id);
description=itemView.findViewById(R.id.description_id);
image=itemView.findViewById(R.id.image_id);
contributordate=itemView.findViewById(R.id.contributordate_id);
}
}
}
第 11 步:使用 MainActivity。Java
在我们的活动中,我们将使用 Android 快速库向新闻 API 发出 GET 请求,并使用新闻文章填充 RecyclerView。首先,我们将创建一个字符串变量并将其设置为 API 密钥(我们在步骤 4 中创建的密钥)。例如,如果您的 API 密钥 = b971358de21d4af48ae24b5faf06bbok。然后将变量声明为:
private static String API_KEY="b971358de21d4af48ae24b5faf06bbok";
下面是MainActivity 的代码。 Java文件。
Java
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import com.androidnetworking.AndroidNetworking;
import com.androidnetworking.common.Priority;
import com.androidnetworking.error.ANError;
import com.androidnetworking.interfaces.JSONObjectRequestListener;
import com.jacksonandroidnetworking.JacksonParserFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
// TODO : set the API_KEY variable to your api key
private static String API_KEY="";
// setting the TAG for debugging purposes
private static String TAG="MainActivity";
// declaring the views
private ProgressBar mProgressBar;
private RecyclerView mRecyclerView;
// declaring an ArrayList of articles
private ArrayList mArticleList;
private ArticleAdapter mArticleAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// initializing the Fast Android Networking Library
AndroidNetworking.initialize(getApplicationContext());
// setting the JacksonParserFactory
AndroidNetworking.setParserFactory(new JacksonParserFactory());
// assigning views to their ids
mProgressBar=(ProgressBar)findViewById(R.id.progressbar_id);
mRecyclerView=(RecyclerView)findViewById(R.id.recyclerview_id);
// setting the recyclerview layout manager
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
// initializing the ArrayList of articles
mArticleList=new ArrayList<>();
// calling get_news_from_api()
get_news_from_api();
}
public void get_news_from_api(){
// clearing the articles list before adding news ones
mArticleList.clear();
// Making a GET Request using Fast
// Android Networking Library
// the request returns a JSONObject containing
// news articles from the news api
// or it will return an error
AndroidNetworking.get("https://newsapi.org/v2/top-headlines")
.addQueryParameter("country", "in")
.addQueryParameter("apiKey",API_KEY)
.addHeaders("token", "1234")
.setTag("test")
.setPriority(Priority.LOW)
.build()
.getAsJSONObject(new JSONObjectRequestListener(){
@Override
public void onResponse(JSONObject response) {
// disabling the progress bar
mProgressBar.setVisibility(View.GONE);
// handling the response
try {
// storing the response in a JSONArray
JSONArray articles=response.getJSONArray("articles");
// looping through all the articles
// to access them individually
for (int j=0;j
输出: