آموزش خواندن Rss در برنامه نویسی اندروید
سلام دوستان در این سری از آموزش های برنامه نویسی اندروید به آموزش خواندن Rss در برنامه نویسی اندروید می پردازیم این آموزش به در خواست یکی از کاربران ایجاد شده است با ما همراه باشید. باید ابتدا اشاره کنیم ممکن است rss بعضی از سایت ها سفارشی شده باشید و برنامه نتواند آن ها را بخواند ولی به طور معمول rss بیشتر سایت ها شبیه هم هستند.
قبل از هرچیز وارد فایل Build.gradle شده و کتاب خانه های زیر را اضافه کنید.(در بخش dependencies)
compile 'com.android.support:appcompat-v7:25.0.1'
compile 'com.android.support:recyclerview-v7:25.0.1'
compile 'com.android.support:design:25.0.1'
سپس پروژه رو Sync کنید (علت خطاهای گریدل را برای شما بررسی کردیم کافی است در سایت سرچ کنید )
بخش activity_main.xml ما همانند زیر می شود.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.sample.foo.simplerssreader.MainActivity">
<Button
android:id="@+id/fetchFeedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:text="Fetch" />
<android.support.design.widget.TextInputLayout
android:id="@+id/textInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:layout_toStartOf="@id/fetchFeedButton"
android:hint="Rss feed source">
<EditText
android:id="@+id/rssFeedEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>
<TextView
android:id="@+id/feedTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/textInputLayout"
android:text="Feed Title: " />
<TextView
android:id="@+id/feedDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/feedTitle"
android:text="Feed Description: " />
<TextView
android:id="@+id/feedLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/feedDescription"
android:text="Feed Link: " />
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/feedLink"
android:layout_marginTop="@dimen/activity_vertical_margin">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
و بخش layout ما شامل یک دکمه سه تا TextView یک input یا همان EditText و یک SwipeRefreshLayout و یک Recycler view (دوست عزیزی که سوال پرسیده بود گفتن در Recyclerview قرار بدهیم به همین علت از آن هم استفاده کردیم.) SwipeRefreshLayout به کاربر اجازه می دهد تا زمانی که از بالا به پایین بروی اکتیویتی کشید یک progress bar قشنگ به نمایش در می آید و صفحه را تازه سازی (refresh) می کند به طور مثال برای دریافت دیتا صفحه refresh می شود.
قبلتر ما recyclerview را توضیح دادیم. حالا باید برای recycler view ایتم های آن را درست کنیم یعنی مقدارهایی که می خواهد نمایش داده شود.
پس مثل زیر عمل می کنیم.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/titleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold" />
<TextView
android:id="@+id/descriptionText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/linkText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/colorAccent" />
</LinearLayout>
کد بالا هر ایتم از Recycler view را به وجود می آورد یعنی کل کد بالا شبیه به یک لیست در یک ایتم قرار می گیرد.
برای اینکه مقدارها را در هرکدوم از آنها ست بشه باید یک کلاسی درست کنیم که title و description و link را در هر یکی از آیتم های Recycler view قرار دهد.
public class RssFeedModel {
public String title;
public String link;
public String description;
public RssFeedModel(String title, String link, String description) {
this.title = title;
this.link = link;
this.description = description;
}
}
حالا برای اینکه مقدار ها در هر item ست بشن (قرار داده شوند) باید برای کلاس بالا یک آداپتور درست کنیم پس مثل زیر عمل می کنیم.
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import java.util.List;
/**
* Created by Jeferson on 27/11/2017.
*/
public class RssFeedListAdapter
extends RecyclerView.Adapter<RssFeedListAdapter.FeedModelViewHolder> {
private List<RssFeedModel> mRssFeedModels;
public static class FeedModelViewHolder extends RecyclerView.ViewHolder {
private View rssFeedView;
public FeedModelViewHolder(View v) {
super(v);
rssFeedView = v;
}
}
public RssFeedListAdapter(List<RssFeedModel> rssFeedModels) {
mRssFeedModels = rssFeedModels;
}
@Override
public FeedModelViewHolder onCreateViewHolder(ViewGroup parent, int type) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_rss_feed, parent, false);
FeedModelViewHolder holder = new FeedModelViewHolder(v);
return holder;
}
@Override
public void onBindViewHolder(FeedModelViewHolder holder, int position) {
final RssFeedModel rssFeedModel = mRssFeedModels.get(position);
((TextView)holder.rssFeedView.findViewById(R.id.titleText)).setText(rssFeedModel.title);
((TextView)holder.rssFeedView.findViewById(R.id.descriptionText)).setText(rssFeedModel.description);
((TextView)holder.rssFeedView.findViewById(R.id.linkText)).setText(rssFeedModel.link);
}
@Override
public int getItemCount() {
return mRssFeedModels.size();
}
}
و بعد از آن کد های مربوط به MainActivty.java را قرار می دهیم.(در ادامه آنها را توضیح خواهیم داد)
import android.os.AsyncTask;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.util.Xml;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private RecyclerView mRecyclerView;
private EditText mEditText;
private Button mFetchFeedButton;
private SwipeRefreshLayout mSwipeLayout;
private TextView mFeedTitleTextView;
private TextView mFeedLinkTextView;
private TextView mFeedDescriptionTextView;
private List<RssFeedModel> mFeedModelList;
private String mFeedTitle;
private String mFeedLink;
private String mFeedDescription;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mEditText = (EditText) findViewById(R.id.rssFeedEditText);
mFetchFeedButton = (Button) findViewById(R.id.fetchFeedButton);
mSwipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
mFeedTitleTextView = (TextView) findViewById(R.id.feedTitle);
mFeedDescriptionTextView = (TextView) findViewById(R.id.feedDescription);
mFeedLinkTextView = (TextView) findViewById(R.id.feedLink);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mFetchFeedButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new FetchFeedTask().execute((Void) null);
}
});
mSwipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new FetchFeedTask().execute((Void) null);
}
});
}
public List<RssFeedModel> parseFeed(InputStream inputStream) throws XmlPullParserException, IOException {
String title = null;
String link = null;
String description = null;
boolean isItem = false;
List<RssFeedModel> items = new ArrayList<>();
try {
XmlPullParser xmlPullParser = Xml.newPullParser();
xmlPullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
xmlPullParser.setInput(inputStream, null);
xmlPullParser.nextTag();
while (xmlPullParser.next() != XmlPullParser.END_DOCUMENT) {
int eventType = xmlPullParser.getEventType();
String name = xmlPullParser.getName();
if(name == null)
continue;
if(eventType == XmlPullParser.END_TAG) {
if(name.equalsIgnoreCase("item")) {
isItem = false;
}
continue;
}
if (eventType == XmlPullParser.START_TAG) {
if(name.equalsIgnoreCase("item")) {
isItem = true;
continue;
}
}
Log.d("MainActivity", "Parsing name ==> " + name);
String result = "";
if (xmlPullParser.next() == XmlPullParser.TEXT) {
result = xmlPullParser.getText();
xmlPullParser.nextTag();
}
if (name.equalsIgnoreCase("title")) {
title = result;
} else if (name.equalsIgnoreCase("link")) {
link = result;
} else if (name.equalsIgnoreCase("description")) {
description = result;
}
if (title != null && link != null && description != null) {
if(isItem) {
RssFeedModel item = new RssFeedModel(title, link, description);
items.add(item);
}
else {
mFeedTitle = title;
mFeedLink = link;
mFeedDescription = description;
}
title = null;
link = null;
description = null;
isItem = false;
}
}
return items;
} finally {
inputStream.close();
}
}
private class FetchFeedTask extends AsyncTask<Void, Void, Boolean> {
private String urlLink;
@Override
protected void onPreExecute() {
mSwipeLayout.setRefreshing(true);
mFeedTitle = null;
mFeedLink = null;
mFeedDescription = null;
mFeedTitleTextView.setText("Feed Title: " + mFeedTitle);
mFeedDescriptionTextView.setText("Feed Description: " + mFeedDescription);
mFeedLinkTextView.setText("Feed Link: " + mFeedLink);
urlLink = mEditText.getText().toString();
}
@Override
protected Boolean doInBackground(Void... voids) {
if (TextUtils.isEmpty(urlLink))
return false;
try {
if(!urlLink.startsWith("http://") && !urlLink.startsWith("https://"))
urlLink = "http://" + urlLink;
URL url = new URL(urlLink);
InputStream inputStream = url.openConnection().getInputStream();
mFeedModelList = parseFeed(inputStream);
return true;
} catch (IOException e) {
Log.e(TAG, "Error", e);
} catch (XmlPullParserException e) {
Log.e(TAG, "Error", e);
}
return false;
}
@Override
protected void onPostExecute(Boolean success) {
mSwipeLayout.setRefreshing(false);
if (success) {
mFeedTitleTextView.setText("Feed Title: " + mFeedTitle);
mFeedDescriptionTextView.setText("Feed Description: " + mFeedDescription);
mFeedLinkTextView.setText("Feed Link: " + mFeedLink);
// Fill RecyclerView
mRecyclerView.setAdapter(new RssFeedListAdapter(mFeedModelList));
} else {
Toast.makeText(MainActivity.this,
"Enter a valid Rss feed url",
Toast.LENGTH_LONG).show();
}
}
}
}
توضیح کد بالا از حوصله این بخش خارج است اما ما بخش هایی رو که مهم است به طور سریع به آنها اشاره می کنیم ما ابتدا یک کلاس ایجاد کردیم تا rss را parse کند یعنی اطلاعات رو به صورت درست برای نمایش دهد و کلی از بخش ها بررسی می شود به طور مثال اگر کاربر سایت رو بدون http یا https وارد کند ما خودمان به آن http اضافه می کنیم دوست عزیزمون اشاره کرده بود فقط یک مقدار دریافت شود به همین علت در ابتدا برای سه تا TextView داریم که اطلاعات اولی در آن قرار گرفته می شود سپس بقیه آن در recycler view قرار می گیرد برای sync بودن برنامه هم ما از Async task استفاده کردیم. این آموزش به درخواست یکی از دوستان ایجاد شده است و استفاده از این آموزش نیاز به پیش نیازی هایی دارد.
و در اخر شما باید دسترسی استفاده از اینترنت را در AndroidManifest.xml قرار دهید.
<uses-permission android:name="android.permission.INTERNET" />
این آموزش هم به پایان رسید.
موفق باشید.
آموزش برنامه نویسی اندروید |
عالییییی
خواهش می کنم
موفق باشید
سلام
تو ریسایکلر که نشون میده موضوع title با description همخونی نداره یه چک بفرمایید