选择 json 对象时 ListView OnItemClickListener 崩溃

Posted

技术标签:

【中文标题】选择 json 对象时 ListView OnItemClickListener 崩溃【英文标题】:ListView OnItemClickListener Crash when selecting json object 【发布时间】:2018-06-11 15:12:19 【问题描述】:

当我尝试从searchActivity.java 检索要使用的 JSON 对象到searchDetail.java 时,应用程序崩溃。似乎函数getInfo() 导致了这个问题。最初getInfo()中的list_data的大小为10,但是从searchActivity.java中调用后,大小变成了0。请问我该怎么做才能解决这个问题?

DataParser.java

public class DataParser extends AsyncTask<Void,Void,Integer> 
Context c;
ArrayList<Herb> herb=new ArrayList<>();
ArrayList<HashMap<String, String>> list_data = new ArrayList<HashMap<String, String>>();
HashMap<String,String> data = new HashMap<>();

public DataParser(ListView lv)
    this.lv = lv;


public DataParser(Context c, String jsonData, ListView lv) 
    this.c = c;
    this.jsonData = jsonData;
    this.lv = lv;

@Override
protected Integer doInBackground(Void... params) 
    return this.parseData();

@Override
protected void onPostExecute(Integer result) 
    super.onPostExecute(result);
    pd.dismiss();
    if(result==0)
    
        Toast.makeText(c,"Unable To Parse",Toast.LENGTH_SHORT).show();
    else 
        //BIND DATA TO LISTVIEW
        CustomAdapter adapter=new CustomAdapter(c,herb);
        lv.setAdapter(adapter);
    

private int parseData()

    try
    
        JSONArray ja=new JSONArray(jsonData);
        JSONObject jo=null;
        herb.clear();
        Herb Herb;
        for(int i=0;i<ja.length();i++)
        
            jo=ja.getJSONObject(i);
            String id=jo.getString("h_id");
            String name=jo.getString("h_name");
            String imageUrl=jo.getString("h_image");
            Herb=new Herb();
            Herb.setId(id);
            Herb.setName(name);
            Herb.setImageUrl(imageUrl);
            herb.add(Herb);

            data.put("id",id);
            data.put("name",name);
            data.put("imageUrl",imageUrl);
           list_data.add(data);
        
        DataStorage.map = getInfo();
        return 1;
     catch (JSONException e) 
        e.printStackTrace();
    
    return 0;

public ArrayList<HashMap<String, String>> getInfo()
    return this.list_data = list_data;

searchActivity.java

public class searchActivity extends AppCompatActivity

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_search);

    ListView lv= (ListView) findViewById(R.id.HerbListView);
    Downloader dl = new Downloader(searchActivity.this,urlAddress,lv);
    dl.execute();
    final DataParser dp = new DataParser(lv);
    lv.setOnItemClickListener (new AdapterView.OnItemClickListener() 
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
        try
            ArrayList<HashMap<String, String>> list_data = DataStorage.map;
            String hid = list_data.get(position).get("id");
            String name = list_data.get(position).get("name");
            String imageUrl = list_data.get(position).get("imageUrl");

            Intent intent = new Intent(searchActivity.this, searchDetail.class);
            intent.putExtra("id", hid);
            intent.putExtra("name", name);
            intent.putExtra("imageUrl", imageUrl);
            startActivity(intent);
        
        catch (NullPointerException e)
            e.printStackTrace();
        
    
);

searchDetail.java

public class searchDetail extends AppCompatActivity 
@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_search_detail);
    String name = getIntent().getStringExtra("name");
    String imageUrl = getIntent().getStringExtra("imageUrl");

    TextView txt1= (TextView) findViewById(R.id.txtHName);
    ImageView img= (ImageView) findViewById(R.id.imageHerb);

    txt1.setText(name);
    Picasso.with(this).load(imageUrl).fit().into(img);

DataStorage.java

public class DataStorage 
public static ArrayList<HashMap<String,String>> map = new ArrayList<>();

activity_search_detail.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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:layout_
android:layout_>

<RelativeLayout
    android:layout_
    android:layout_
    android:orientation="vertical">

    <ImageView
        android:id="@+id/imageHerb"
        android:layout_
        android:layout_
        android:layout_centerHorizontal="true"
        android:scaleType="fitXY" />

    <TextView
        android:id="@+id/lblHName"
        android:layout_
        android:layout_
        android:layout_below="@id/imageHerb"
        android:paddingTop="10dp"
        android:text="Herb Name: " />

    <TextView
        android:id="@+id/txtHName"
        android:layout_
        android:layout_
        android:layout_below="@id/imageHerb"
        android:layout_toEndOf="@id/lblHName"
        android:paddingTop="10dp"
        android:text="TextView" />


</RelativeLayout>

当前生成的 logcat

java.lang.IllegalStateException: Circular dependencies cannot exist in RelativeLayout

P/S:我在activity_search_detail.xml中找不到任何循环依赖

【问题讨论】:

在 searchActivity 中创建 DataParser 后,什么时候将任何元素放入列表中? 检查我的答案dp.execute();在点击之前添加这个.. 如果完成则更新... @SantanuSur 当我这样做时应用程序崩溃了。发生这种情况可能是因为当 Downloader 类运行时,DataParser 类也会运行 @TomekK i 将元素绑定到 onPostExecute 函数中的列表视图 lv.setAdapter(adapter) 【参考方案1】:

首先执行 DataParser 类 ..new DataParser( lv).execute() 或者在你的情况下是 dp.execute() 你缺少这个语句。如果你没有执行 AsyncTask 类它不会在 doInBackground() 中执行任何任务。希望它能解决您的问题..dp.getinfo() 将始终返回一个空白列表...创建另一个名为 class holdHashmapList public static ArrayList<Hashmap<String,String>> map= new ArrayList<>(); 的类,并在 dataParser 类中 holdHashmapList.map =getInfo(); 和 onItemClick 侦听器中...Arralist&lt;map&lt;&gt;&gt; = holdHashmapList.map; 您正在构建的哈希图将始终包含最后一个对象...在parseData 函数中...所以在data.put("id"); 之前只需添加data=new HashMap&lt;&gt;();

【讨论】:

当我这样做时应用程序崩溃。发生这种情况可能是因为当 Downloader 类运行时,DataParser 类也会运行 我添加了崩溃 不懂就问 DataParser类去ParseData()方法然后去getInfo();而不是只写holdHashmapList.map = getInfo(); 在这种情况下不要写dp.execute();@DreamCrusher【参考方案2】:

您必须执行 DataParser(dp) 才能在 SearchActivity 中填充您的 list_data。仅初始化 DataParser 不会填充 list_data。

public class searchActivity extends AppCompatActivity

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_search);

    ListView lv= (ListView) findViewById(R.id.HerbListView);
    Downloader dl = new Downloader(searchActivity.this,urlAddress,lv);
    dl.execute();
    final DataParser dp = new DataParser(lv);
    dp.execute();     // update 
    lv.setOnItemClickListener (new AdapterView.OnItemClickListener() 
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long 
                         id) 
        try
            ArrayList<HashMap<String, String>> list_data = dp.getInfo();
            String hid = list_data.get(position).get("id");
            String name = list_data.get(position).get("name");
            String imageUrl = list_data.get(position).get("imageUrl");

            Intent intent = new Intent(searchActivity.this, searchDetail.class);
            intent.putExtra("id", hid);
            intent.putExtra("name", name);
            intent.putExtra("imageUrl", imageUrl);
            startActivity(intent);
        
        catch (NullPointerException e)
            e.printStackTrace();
        
     
    );
  

【讨论】:

当我这样做时应用程序崩溃。发生这种情况可能是因为当 Downloader 类运行时,DataParser 类也会运行。

以上是关于选择 json 对象时 ListView OnItemClickListener 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin.Forms JSON 对象到 Listview

如何在 c# 中使用 JSON 使用 foreach 序列化多个项目?

如何使用 JSON 响应,它为我提供了一个带有对象的数组来设置我的 ListView

如何基于 JSON 对象构建 ListView 并在 onItemClick 之后传递其数据

ListView 对象上的 SaveInstanceState

单个 ListView 中的不同对象