Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have article view where each post of mine will show details (think of it as blog post) but i cannot parse the data so i get my app closed instead of details of my articles.

code

ArticlesAdapter.kt

class ArticlesAdapter(val article : ArrayList<Article>) : RecyclerView.Adapter<ArticlesAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view: View =
            LayoutInflater.from(parent.context).inflate(R.layout.fragment_articles, parent, false)
        return ViewHolder(view)
    }

    override fun getItemCount(): Int {
        return article.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.textView.text = article.get(position).name

        Glide.with(holder.aImage.context)
            .load(article.get(position).image)
            .placeholder(R.drawable.placeholder2)
            .error(R.drawable.placeholder2)
            .fallback(R.drawable.placeholder2) // if load was null
            .into(holder.aImage)

        Log.e("ImageURL", "URL = " + article.get(position).image)
    }


    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var textView: TextView
        var aImage: ImageView

        init {
            textView = itemView.findViewById(R.id.text_name)
            aImage = itemView.findViewById(R.id.a_image)
        }
    }
}

ArticlesDetail.tk (my activity)

class ArticlesDetail : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.article_details)

        callAPIDemo()
    }

    // api code
    private fun callAPIDemo() {
        val mySlugValue: String = intent.getStringExtra("my_slug")
        Log.d("myslug in:", mySlugValue)
        // Instantiate the RequestQueue.
        val queue = Volley.newRequestQueue(this)
        val url = "https://example.com/api/articles/$mySlugValue"

        // Request a string response from the provided URL.
        val stringRequest = StringRequest(
            Request.Method.GET, url,
            Response.Listener<String> { response ->

                val list: ArrayList<Article> = ArrayList()
                getPosts(response,list)

                // here you will have the complete list of data in your "list" variable
                article_det.layoutManager = LinearLayoutManager(this)
                Log.d("my list", list.toString())
                article_det.adapter = ArticlesAdapter(list)
            },
            Response.ErrorListener { error ->
                //displaying the error in toast if occurrs
                Toast.makeText(applicationContext, error.message, Toast.LENGTH_SHORT)
                    .show()
            })
        // Add the request to the RequestQueue.
        queue.add(stringRequest)
    }


    fun getPosts(response: String,list:ArrayList<Article>) {

        var jsonObject = JSONObject(response)
        val jsonArray = jsonObject.getJSONArray("article")

        for (i in 0 until jsonArray.length()) {
            val jsonObject1 = jsonArray.getJSONObject(i)
            var listingObject = Article(
                jsonObject1.getInt("id"),
                jsonObject1.getString("name"),
                jsonObject1.getString("slug"),
                jsonObject1.getString("image"),
                jsonObject1.getString("body"),
                jsonObject1.getString("icon"),
                jsonObject1.getString("quote"),
                jsonObject1.getString("video"),
                jsonObject1.getString("user"),
                jsonObject1.getString("created_at"),
                jsonObject1.getString("updated_at")

            )
            list.add(listingObject)

        }
    }
}

Article.kt (my class)

data class Article (
    val id: Int,
    val name: String?,
    val slug: String?,
    val image: String?,
    val body: String?,
    val icon: String?,
    val quote: String?,
    val user: String?,
    val video: String?,
    val created_at: String?,
    val updated_at: String?
)

then for views i have this 2 files:

article_details.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/article_det"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:textAlignment="center"
        android:textSize="20sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

and fragment_articles.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp">

    <ImageView
        android:id="@+id/a_image"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:contentDescription="@string/image"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/text_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginEnd="20dp"
        android:textSize="18sp"
        app:layout_constraintBottom_toBottomOf="@+id/a_image"
        app:layout_constraintStart_toEndOf="@+id/a_image"
        app:layout_constraintTop_toTopOf="@+id/a_image" />

</androidx.constraintlayout.widget.ConstraintLayout>

Obviously this last xml file will be edited in future to get more details of my articles such as body or user etc. but for now to test returned data i think having name and image of article is enough.

Data

this is how my returned data in this activity looks like,

one

Error

    Caused by: org.json.JSONException: No value for article
    at org.json.JSONObject.get(JSONObject.java:392)
    at org.json.JSONObject.getJSONArray(JSONObject.java:587)
    at ui.ArticlesDetail.ArticlesDetail.getPosts(ArticlesDetail.kt:63)
    at ui.ArticlesDetail.ArticlesDetail$callAPIDemo$stringRequest$1.onResponse(ArticlesDetail.kt:43)
    at ui.ArticlesDetail.ArticlesDetail$callAPIDemo$stringRequest$1.onResponse(ArticlesDetail.kt:18)

my line 63: val jsonArray = jsonObject.getJSONArray("article")

my line 43: getPosts(response,list)

my line 18: class ArticlesDetail : AppCompatActivity() {

Question

  1. Any idea which part of my callAPIDemo() function or getPosts() function causing error?
  2. how can I fix it?

Update

my json data:

{
  "id": 4,
  "user": "...",
  "name": "...",
  "slug": "...",
  "image": "...",
  "body": "...",
  "icon": null,
  "quote": null,
  "video": null,
  "categories": [
    {
      "id": 10,
      "name": "...",
      "slug": "...",
      "icon": "..",
      "body": "...",
      "image": "...",
      "created_at": "2019-11-23 05:35:31",
      "updated_at": "2019-11-26 11:25:17"
    }
  ],
  "created_at": "2019-11-23 07:34:10",
  "updated_at": "2019-11-23 07:37:52"
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
114 views
Welcome To Ask or Share your Answers For Others

1 Answer

Actually the name of your Array is categories not article

so in this line of your code val jsonArray = jsonObject.getJSONArray("article"), instead of article you need to add categories

something like below

val jsonArray = jsonObject.getJSONArray("categories")

EDIT 1 :-

As discussed your article_details.xml will be like below

Here you can change size and margins, as you want

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/article_image"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:layout_marginStart="15dp"
        android:layout_marginEnd="15dp"
        android:src="@mipmap/ic_launcher"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <TextView
        android:id="@+id/username"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="30dp"
        android:layout_marginTop="15dp"
        android:maxLines="1"
        android:text="userName"
        android:textSize="14sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/article_image" />


    <TextView
        android:id="@+id/article_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="30dp"
        android:layout_marginTop="5dp"
        android:maxLines="1"
        android:text="Article name"
        android:textSize="18sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/username" />


    <TextView
        android:id="@+id/article_body"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="15dp"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="15dp"
        android:text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. "
        android:textSize="20sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/article_name" />

</androidx.constraintlayout.widget.ConstraintLayout>

Now just do the findfindViewById in your ArticlesDetail class so you can set values on them when you receive data from your API

EDIT 2:-

Now Your ArticlesDetail will be like

class ArticlesDetail : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration


    var username: TextView? = null
    var articleName: TextView? = null
    var articleBody: TextView? = null
    var articleImage: ImageView? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)

        username = findViewById(R.id.username)
        articleName = findViewById(R.id.article_name)
        articleBody = findViewById(R.id.article_body)
        articleImage = findViewById(R.id.article_image)

        callAPIDemo()
    }

    // api code
    private fun callAPIDemo() {
        val mySlugValue: String = intent.getStringExtra("my_slug")
        Log.d("myslug in:", mySlugValue)
        // Instantiate the RequestQueue.
        val queue = Volley.newRequestQueue(this)
        val url = "https://example.com/api/articles/$mySlugValue"

        // Request a string response from the provided URL.
        val stringRequest = StringRequest(
                Request.Method.GET, url,
                Response.Listener<String> { response ->


                    parseAndSetValues(response)

                },
                Response.ErrorListener { error ->
                    //displaying the error in toast if occurrs
                    Toast.makeText(applicationContext, error.message, Toast.LENGTH_SHORT)
                            .show()
                })
        // Add the request to the RequestQueue.
        queue.add(stringRequest)
    }


    private fun parseAndSetValues(response: String) {


        val jsonObject = JSONObject(response)


        username!!.text = jsonObject.getString("user")
        articleName!!.text = jsonObject.getString("name")
        articleBody!!.text = jsonObject.getString("body")
        Glide.with(this).load(jsonObject.getString("image")).into(articleImage!!)


    }


}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...