بناء تطبيق بلوجر و الاستعانة ب recyclerView من خلال الكوتلن
06 September
قبل مدة ليست بالبعيدة لتستطيع جلب نص JSON من الانترنيت ثم نقله الى دالة تقوم باستخراج المعلومات المطلوبة منه ثم الحاقها ب Data class ومنه الى Adapter كان يجب ان تكون محترفا و لمكتبات مساعدة او نقل و لصق لمجموعة من الاكواد دون فهمها لكن الان مع كوتلن اصبح الامر اسهل و دون حاجة الى مكتبات هذا ما سنراه في هذه التدوينة .
هي نفس المراحل لكن باسلوب ابسط ولكي تفهم اكثر لدينا Api الخاص باحدى مدوناتي التجريبة على بلوجر .
ما نرغب به هو استخراج عنوان و محتوى و صورة التدوينة لهذا سنحتاج الى مكتبة Picasso .
لهذا اضف حقنة المكتبة من خلال ملف build.gradle :
لهذا اضف حقنة المكتبة من خلال ملف build.gradle :
dependencies {
//....
implementation 'com.squareup.picasso:picasso:2.5.2'
}
ان كنت تستعمل جوجل كروم سيظهر JSON بطريقة غير مرتبة لذا حاول ايجاد اضافة تساعد على قراءة JSON |
feed: JSONObject entry: JSONArray
title: JSONObject
$t content: JSONObject $t media$thumbnail: JSONObject url
اما على الاندرويد ستوديو فاليك الملفات التي ساستعين بها: 5 ملفات فقط
نقوم بانشاء ملفات Xml :
في الملف الرئيسي : سنضع recyclerView مع button لجلب باقي التدوينات و ProgressBar لاظهار شريط عند جلب البيانات.
قبل كل شيء نقوم بانشاء ملف dataClass يستقبل ثلاث متغيرات title content imgUrl
اولا سنقوم باضافة كلاس اسمه mAdapter
نقوم بانشاء ملفات Xml :
في الملف الرئيسي : سنضع recyclerView مع button لجلب باقي التدوينات و ProgressBar لاظهار شريط عند جلب البيانات.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/hostLayout"
android:layout_width="match_parent"
android:background="#e7e6e6"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/pBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-7dp"
android:indeterminate="true"
/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_margin="10dp"
app:backgroundTint="#fff"
app:elevation="20dp"
app:srcCompat="@mipmap/ic_launcher"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/items"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/pBar"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
</RelativeLayout>
ثم قم بانشاء ملف xml ليكون الذي ستظهر فيه التدوينات ببساطة فيه مكان للصورة و العنوان و محتوى التدوينة :
right click on layout => New =>LayoutRecourceFile=> name=> ok
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_margin="20px"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/thumb"
android:layout_width="match_parent"
android:layout_height="190dp"/>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10px"
android:padding="5px"
android:textSize="20dp"
android:background="@color/colorPrimaryDark"
android:textColor="@android:color/white"/>
<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="40dp"
android:textSize="20dp"
android:padding="2px"
android:background="@android:color/white"
android:layout_alignBottom="@+id/thumb"/>
</RelativeLayout>
نتقل الان الى ملفات الكوتلن :قبل كل شيء نقوم بانشاء ملف dataClass يستقبل ثلاث متغيرات title content imgUrl
data class Posts(
var title: String? = null,
var content: String? = null,
var imgUrl: String? = null
)
اولا سنقوم باضافة كلاس اسمه mAdapter
right Click app => New => kotlin Class/File => name :mAdapter =>ok
class mAdapter(var lists: List) : RecyclerView.Adapter() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
Item( LayoutInflater.from(parent.context).inflate(R.layout.list_layout, parent, false))
override fun getItemCount() = lists.size
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) =(holder as Item).bindData(lists[position])
class Item(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bindData(post: Posts) {
//عنوان التدوينة
itemView.title.text = post.title
// ارجاع جزء من التدوينة بعد تحويلها الى نص عادي
itemView.content.text = TextUtils.substring(Html.fromHtml(post.content),0,50)
if(!post.imgUrl.isNullOrEmpty()){
//تحميل الصورة باستعمال مكتبة بكاسو
Picasso.with(itemView.context).load(post.imgUrl)
.fit().into(itemView.thumb)
}
}
}
}
لم يتبقى الكثير الان اذهب الى الملف الرئيسي
في هذا الملف سنجلب JSON من الويب على شكل string ثم نقوم باستخراج المعلومات التي نرغب بها بعد ذلك نحيل المعلومات الى adapter ليضعها في recyclerView .
و نكون بهذا قد انتهينا من احد التطبيقات التي سعدتنا كوتلن فيها بقوة و ترقبوا تطبيق مفتح المصدر منا باذن الله .
class Main : AppCompatActivity() {
internal var json = ""
internal lateinit var lista: ArrayList
lateinit var adapter:mAdapter
var perPage:Int=11
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.ac_main)
lista= ArrayList()
items.layoutManager = LinearLayoutManager(this)
adapter=mAdapter(lista)
items.adapter = adapter
// جلب البيانات في الخلفية دن اية عرقلة
//الرابط به 10 تدوينات كحد اقصى
GetJson().execute("http://www.androdihow.blogspot.com/feeds/posts/default?alt=json&max-results=10")
//عند الظغط على هذا الزر سيتم تحميل المزيد من التدوينات
fab.setOnClickListener {
// الرابط به عشر تدوينات كحد اقصى و نقطة البدأ
GetJson().execute("http://www.androdihow.blogspot.com/feeds/posts/default?alt=json&max-results=10&start-index=$perPage")
perPage+=10
}
}
private inner class GetJson : AsyncTask < String, Int, String > () {
override fun onPreExecute() {
super.onPreExecute()
// اضهار الشريط
pBar.visibility= View.VISIBLE
}
override fun doInBackground(vararg urls: String): String {
try {
return URL(urls[0]).readText()
}catch (e:Exception){
return ""
}
}
override fun onPostExecute(result: String) {
if (!result.isNullOrEmpty()) {
json = result
parseJSON(json)
}else{
//عدم وجود انترنيت
//مشكلة في api
}
}
}
fun parseJSON(json: String) {
try{
val jsonObj = JSONObject(json)
// الوصول الى feed
val feed = jsonObj.getJSONObject("feed")
//جعل الاونتري مثل array
val posts = feed.getJSONArray("entry")
// عمل لوب على كل التدوينات
for (i in 0..posts.length()-1) {
val post = Posts()
val p=posts.getJSONObject(i)
//عنوان التدوينة
val title=p.getJSONObject("title").getString("\$t")
//محتوى التدوينة
val content=p.getJSONObject("content").getString("\$t")
//صورة التدوينة
val img=p.getJSONObject("media\$thumbnail").getString("url").replace("/s72-c","")
//حفظ البيانات في dataclass
post.title=title
post.content=content
post.imgUrl=img
// اضافة التدوينة الى القائمة
lista.add(post)
//لوب من جديد
}
//اعلام بان هناك تدوينات جديدة
adapter.notifyItemInserted(lista.size-1)
}catch (ex:Exception){
//في حالة وجود خطا
Log.e("erorr",ex.message.toString())
val snackbar = Snackbar
.make(hostLayout, "يوجد شيء مريب حاول مجددا", Snackbar.LENGTH_INDEFINITE)
.setAction("Refresh", View.OnClickListener {
GetJson()
.execute("http://www.androdihow.blogspot.com/feeds/posts/default?alt=json")
})
snackbar.show()
}
//ايقاف الشريط
pBar.visibility= View.GONE
}
}
و نكون بهذا قد انتهينا من احد التطبيقات التي سعدتنا كوتلن فيها بقوة و ترقبوا تطبيق مفتح المصدر منا باذن الله .
اليك بعض الدروس الاخرى التي قد تفيدك:
اترك لنا تعليقا