【问题标题】:Troubles with JSON parsingJSON解析的问题
【发布时间】:2019-04-23 11:07:23
【问题描述】:

我正在开发一个简单的新闻应用程序。 我需要从远程服务器以 JSON 格式获取数据,然后将其放在视图中。我使用 TabLayout 和 recyclerView 来显示数据类别和 Volley 用于查询这里没有 API。

TabLayout 是根据来自 JSON 的数据自动设置的,我在其中提取选项卡标题,每个选项卡的内容都显示在 recyclerView 上(文章标题、图像、内容、链接...)并在片段中呈现

我花了几个小时尝试调试它,但没有成功。但无论我做什么,都没有显示任何数据。不知道我做错了什么。

我知道这不是要求此类事情的正确地方,但我有点绝望,需要一些有经验的开发人员来解决我的问题。

它是如何工作的:

Activity 启动 BaseArticleFragment,它调用一个加载内容类别并将数据绑定到视图的方法:

@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();
}

启动时,baseArticleFragment 在其 onActivityCreated() 方法中调用 loadCategories() 方法:

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

这里是 loadCategories() 方法:

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();
                    }
                }));
}

我猜问题可能出在查询上,但不确定因为我认为我的逻辑很好

编辑:

这是我需要获取的 JSON 数据:

[
  {
    "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",
  }
]

编辑 2: 我忘记在我的 JSONPArser 类中粘贴 parseCategories() 的代码

 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;
    }

}

【问题讨论】:

  • 您是否检查过您收到的是成功响应而不是错误?
  • 日志上没有错误码,但是onErrorResponse(VolleyError vError)上的snackbar被触发了
  • 在这种情况下,检查“volleyError”以查看返回的错误代码
  • 没有发现错误代码
  • 这很奇怪。如果它正在输入错误响应代码,那么 vError 中必须有一些东西说明它是什么。尝试查看此处:stackoverflow.com/questions/24700582/handle-volley-error 和此处:stackoverflow.com/questions/21867929/…,了解如何准确识别错误类型的示例。

标签: android json android-fragments android-tablayout


【解决方案1】:

试试这个@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();
 }
}

这是适配器类

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>

【讨论】:

  • 这种方式可行,但请记住:我将响应添加到作为 BaseArticleFragment 对象的类别(受保护的静态 ArrayList categories = null;)然后设置我的适配器
  • 正如我试图在我的问题中解释的那样,视图上没有显示任何数据。活动是空白的,我得到 Volley Error timed out
  • 你检查过我的全部答案吗?我的意思是当我以这种方式使用截击时它对我来说很好用
  • 我的做法完全不同。我的 parseCategories() 方法也一样
  • 好的,我会检查@esQmo_
【解决方案2】:

你忘了在“load”方法的最后加上这个东西:

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

尝试添加它...

不要使用new RequestQueue,请使用RequestQueue jsonQueue = new RequestQueue

像这样:

    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);

【讨论】:

  • 有些东西不工作,我只能从小吃店得到错误,
  • @esQmo_ Snackbar 错误?我看到你在 Fragment 中工作,而不是 activity.this,请使用 getActivity()
  • 是的,我修改了它,虽然 IDE 警告它可能为空
  • 但这基本上是我正在做的,我有一个ApplicationController类
  • 不,我有一个白屏,而且总是来自小吃店的消息,所以我猜是 Volley 的错误?
【解决方案3】:

只要检查你是否为 recyclerView 设置了 LayoutManager

recyclerView.setLayoutManager(new LinearLayoutManager(MyActivity.this));

【讨论】:

    【解决方案4】:

    我们也可以获取您的代码和 JSON 数据吗?由于我们无法读取您的想法或计算机上的内容...请对您的帖子进行一些编辑,添加代码和 json 数据,以便我们为您提供帮助。

    【讨论】:

      【解决方案5】:

      由于您收到超时错误,您可以更改超时值,以便它愿意等待更长时间。

      试试这样的:

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

      其中 MY_SOCKET_TIMEOUT_MS 是您希望在超时之前等待的时间量(以毫秒为单位)。从 5000(5 秒)开始,然后玩弄它。

      先做这个

      requestQueue.add(jsonObjectRequest);
      

      【讨论】:

      • 尝试添加线条和玩价值,没有奏效。活动一启动就会出现错误消息
      • 您可以尝试将其移至 onAttach,因为这发生得较早,但不确定是否会有所帮助
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多