1

I'm working on a simple news app. I need to fetch data from a remote server in JSON format then put it in view. I use TabLayout and recyclerView to display data categories and Volley for the query no API here.

The TabLayout is set automatically depending on data from JSON where I extract tabs title and the content of every tab is being displayed on recyclerView (Article title, image, content, links...) and rendered inside a fragment

I spent several hours trying to debug it without success., but whatever I do, no data is being displayed. Not sure what I'm doing wrong.

I know this is not the right place to ask for such things, but I'm a bit of a desperate and would need some experienced developer than me look at my problem.

How it works:

Activity launches BaseArticleFragment which calls a method that loads contents categories and bind the data to the views:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    this.fm = getSupportFragmentManager();
    this.baseArticleFragment = new BaseArticleFragment();
    FragmentTransaction ft = this.fm.beginTransaction();
    ft.add(R.id.fragment_container, this.baseArticleFragment, TAB_LAYOUT_FRAGMENT_TAG); 
    ft.commit();
}

When launched, baseArticleFragment calls loadCategories() method inside its onActivityCreated() method:

@Override
public void onActivityCreated(Bundle savedInstanceState){
    super.onActivityCreated(savedInstanceState);
    loadCategories();
}

here is the loadCategories() method:

private void loadCategories(){
    String url = "http://somesite.com/categories"; //link to grab the json data
    ApplicationController.getInstance().addToRequestQueue(
            new JsonObjectRequest(0, url, null, new Listener<JSONObject>() { //0 is the Volley code for GET method
                @Override
                public void onResponse(JSONObject jsonObject) {
                    BaseArticleFragment.categories = JSONParser.parseCategories(jsonObject);
                    BaseArticleFragment.this.mViewPager.setAdapter(
                            new RecyclerViewFragmentPagerAdapter(BaseArticleFragment.this.getChildFragmentManager(),
                                    BaseArticleFragment.categories));
                    BaseArticleFragment.this.mTabLayout.setupWithViewPager(BaseArticleFragment.this.mViewPager);
                }
            }, new Response.ErrorListener() {
                    @Override
                   public void onErrorResponse(VolleyError vError){
                        Log.d("BaseArticleFragment", "---Volley Error---");
                        Snackbar.make(BaseArticleFragment.this.mTabLayout, R.string.error_load_categories, Snackbar.LENGTH_SHORT)
                                .setAction(R.string.action_retry, new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        BaseArticleFragment.this.loadCategories();
                                    }
                                }).show();
                    }
                }));
}

I guess the problem may be with the query but not sure cause I think my logic here is good

EDIT :

Here is the JSON data I need to fetch:

[
  {
    "name": "Topic 1",
    "tid": "2",
  },
  {
    "name": "Topic 2",
    "tid": "3",
  },
  {
    "name": "Topic 3",
    "tid": "4",
  },
  {
    "name": "Topic 4",
    "tid": "5",
  },
  {
    "name": "Topic 5",
    "tid": "6",
  },
  {
    "name": "Topic 6",
    "tid": "1415",
  },
  {
    "name": "Topic 7",
    "tid": "1414",
  },
  {
    "name": "Topic 8",
    "tid": "1298",
  },
  {
    "name": "Topic 9",
    "tid": "1301",
  },
  {
    "name": "Topic 10",
    "tid": "1299",
  },
  {
    "name": "Topic 11",
    "tid": "1302",
  },
  {
    "name": "Topic 12",
    "tid": "1300",

  },
  {
    "name": "Topic 13",
    "tid": "1297",
  }
]

Edit 2: I forget to paste the code for parseCategories() in my JSONPArser class

 public static ArrayList<Category> parseCategories(JSONObject jsonObject) {
    ArrayList<Category> categoryArrayList = new ArrayList<>();
    try {
        JSONArray categories = jsonObject.getJSONArray("categories");
        Category all = new Category();
        all.setTid("0");
        all.setName(ApplicationController.getInstance().getString(R.string.tab_all));
        categoryArrayList.add(all);
        for (int i = 0; i < categories.length(); i++) {
            JSONObject catObject = categories.getJSONObject(i);
            Category category = new Category();
            category.setTid(catObject.getString("tid"));
            category.setName(catObject.getString("name"));              
            categoryArrayList.add(category);
        }
        return categoryArrayList;

    } catch (JSONException e) {
        e.printStackTrace();
        return null;
    }

}
esQmo_
  • 1,464
  • 3
  • 18
  • 43
  • Have you checked that you are getting a success response and not an error? – theblitz Apr 23 '19 at 11:35
  • There is no error code on the log, but the snackbar on the onErrorResponse(VolleyError vError) got triggered – esQmo_ Apr 23 '19 at 11:42
  • In that case, check in "volleyError" to see what error code is returned – theblitz Apr 23 '19 at 11:55
  • No error code spotted there – esQmo_ Apr 23 '19 at 11:57
  • 1
    That's strange. If it is entering the error Response code then there must be something in vError that says what it is. Try looking here: https://stackoverflow.com/questions/24700582/handle-volley-error and here: https://stackoverflow.com/questions/21867929/android-how-handle-message-error-from-the-server-using-volley/21868734#21868734 for examples of how to identify exactly what type of error it is. – theblitz Apr 23 '19 at 12:11
  • Or should I print it on stacktrace? – esQmo_ Apr 23 '19 at 12:15
  • Also a good idea. And add it as an edit to the question. – theblitz Apr 23 '19 at 12:23
  • I followed the recommendation from the suggested question and I'm getting timeout error – esQmo_ Apr 23 '19 at 12:26

5 Answers5

2

Try this @esQmo_,

StringRequest stringRequest = new StringRequest(url , new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {

                try {
                    JSONArray jsonArray = new JSONArray(response);

                    ArrayList<Hashmap<String,String>> arraylist = new 
                                                            ArrayList<>();
                    for (int i = 0; i < jsonArray.length(); i++) {

                    HashMap<String, String> hashMap = new HashMap<>();
               String name = 
                      jsonArray.getJSONObject(i).getString("name");
                     String tid = 
                     jsonArray.getJSONObject(i).getString("tid");

                     hashMap.put("name", name);
                     hashMap.put("tid ", tid ); 
                     arraylist.add(hashMap);
                     Log.e("response",name + "\n" + tid);
                   }

              attachAdapter(arraylist);

                } catch (JSONException e) {
                    e.printStackTrace();
                }


            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });

        RequestQueue queue = Volley.newRequestQueue(this);
        queue.add(stringRequest);

     //setting adapter data to the RecyclerView
    private void attachAdapter(ArrayList<HashMap<String, String>> 
    arrayList) {

    ExampleAdapter adapter = new ExampleAdapter(arrayList,this);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(adapter);
    adapter.notifyDataSetChanged();
 }
}

This is the adapter class

public class ExampleAdpater extends RecyclerView.Adapter<ExampleAdpater.ExampleViewHolder>{

public ArrayList<HashMap<String,String>> arraylist;

public Context context;

public ExampleAdpater(ArrayList<HashMap<String, String>> arraylist, Context context) {
    this.arraylist= arraylist;
    this.context = context;
}

@NonNull
@Override
public ExampleViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.textLayout,viewGroup,false);
    return new ExampleViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull ExampleViewHolder viewHolder, int i) {

    HashMap<String,String> hashMap = arraylist.get(i);
    viewHolder.name.setText(hashMap.get("name"));
    viewHolder.tid.setText(hashMap.get("tid"));

}

@Override
public int getItemCount() {
    return arraylist.size();
}

public class ExampleViewHolder extends RecyclerView.ViewHolder{

    TextView name,tid;

    public ExampleViewHolder(@NonNull View itemView) {
        super(itemView);

        name = itemView.findViewById(R.id.name);
        tid = itemView.findViewById(R.id.tid);

        name.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(v.getContext(), ""+name.getText().toString(), 
          Toast.LENGTH_SHORT).show();
            }
        });

        }
   }
  }

textLayout.xml

<?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="match_parent"
android:orientation="vertical" >

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/name"
    />

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/tid"
    />


</LinearLayout>
Brahma Datta
  • 1,102
  • 1
  • 12
  • 20
1

You forgot to add this thing at the end of the "load" method:

Volley.newRequestQueue(this).add(jsonRequest);

Try to add it...

Instead of using new RequestQueue, please use RequestQueue jsonQueue = new RequestQueue

Like this:

    RequestQueue requestQueue = Volley.newRequestQueue(this);
        String url = "https://someurl.com/api";
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {

JSONArray ja = new JSONArray(response);

for(int i = 0; i < ja.length(); i++)
{
       JSONObject jo = ja.get(i);

       String name = jo.getString("name");
}

        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("LOG", error.toString());
            }
        });
        requestQueue.add(jsonObjectRequest);
0

Just check if you have set LayoutManager for recyclerView

recyclerView.setLayoutManager(new LinearLayoutManager(MyActivity.this));
Kishita Variya
  • 810
  • 9
  • 19
0

Can we have your code and JSON data too? Since we can't read what's on your mind or on your computer... Plase make some edits to your post, add code and json data so we may help you.

0

Since you are getting a timeout error you can change the timeout value so that it will be willing to wait longer.

Try something like this:

jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(
MY_SOCKET_TIMEOUT_MS, 
DefaultRetryPolicy.DEFAULT_MAX_RETRIES, 
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

where MY_SOCKET_TIMEOUT_MS is amount of time (in milliseconds) you want to wait before a timeout. Start with 5000 (5 seconds) and play around with it.

Do this before

requestQueue.add(jsonObjectRequest);
theblitz
  • 6,683
  • 16
  • 60
  • 114
  • Tried adding the lines and playing with value, didn't work. The error message appear as soon as the activity is launched – esQmo_ Apr 23 '19 at 12:41
  • You could try moving it to onAttach since that happens earlier but not sure if that will help – theblitz Apr 23 '19 at 12:54