无法从 ListView 通过 Intent 正确传递数据

Posted

技术标签:

【中文标题】无法从 ListView 通过 Intent 正确传递数据【英文标题】:Can't correctly pass data through Intent from ListView 【发布时间】:2018-10-19 18:16:21 【问题描述】:

我尝试将我在ListView 中选择的数据项传递给下一个Activity。但我所能做的就是第二个活动是空的或nullpoinexception 错误。我用RecycleView 做的,但是ListView 有一些问题。

主要活动:

public class ListViewPlaces extends AppCompatActivity 

FirebaseFirestore mFirestore = FirebaseFirestore.getInstance();
CollectionReference placeRef = mFirestore.collection("Places");
Query query;
ListView mListView;
String name;
Places places;
ArrayList<Places> randomPlaceList;
PlaceAdapter mAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list_view_places);
    mListView = findViewById(R.id.place_list);

    randomPlaceList = new ArrayList<>();

    Boolean l_check1 = getIntent().getExtras().getBoolean("1");
    Boolean l_check2 = getIntent().getExtras().getBoolean("2");

    if (l_check2)
        query = placeRef.whereEqualTo("colour", "red");
     else if (l_check1)
        query = placeRef.whereEqualTo("size", "1");
     else 
        query = placeRef.whereEqualTo("size", "2");
    
        query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() 
            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) 
                if (task.isSuccessful()) 
                    List<Places> placesList = new ArrayList<>();
                    for (DocumentSnapshot document : task.getResult()) 
                        Places place = document.toObject(Places.class);
                        placesList.add(place);
                    
                    int placeCount = placesList.size();
                    Random randomGenerator = new Random();
                    ArrayList<Places> randomPlaceList = new ArrayList<>();
                    for (int i = 1; i <= 3; i++) 
                        randomPlaceList.add(placesList.get(randomGenerator.nextInt(placeCount)));
                    
                    ListView mListView = (ListView) findViewById(R.id.place_list);
                    mAdapter = new PlaceAdapter(randomPlaceList, getBaseContext());
                    mListView.setAdapter(mAdapter);
                
            
        );


        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() 
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
                Places places = mAdapter.getItem(position);
                Intent intent = new Intent(getApplicationContext(), Card_activity.class);
                intent.putExtra("name", places.getName());
                startActivity(intent);
            
        );

    

我的模型课:

public class Places 
private String image, name;

public Places() 



public Places(String image, String name) 
    this.image = image;
    this.name = name;


public String getImage()  return image; 
public String getName()  return name; 

自定义适配器:

class PlaceAdapter extends ArrayAdapter<Places> 

private ArrayList<Places> dataSet;
Context mContext;

private static class ViewHolder 
    TextView name_text;
    ImageView image_text;


public PlaceAdapter(ArrayList<Places> dataSet, Context context ) 
    super(context, R.layout.item_list, dataSet);

    this.dataSet = dataSet;
    this.mContext = context;



@Override
public View getView(int position, View converView, ViewGroup parent) 

    Places places = getItem(position);
    ViewHolder viewHolder;

    final View result;

    if (converView == null) 
        viewHolder = new ViewHolder();
        LayoutInflater inflater = LayoutInflater.from(getContext());
        converView = inflater.inflate(R.layout.item_list, parent, false);
        viewHolder.name_text = (TextView) converView.findViewById(R.id.text_image_id);
        viewHolder.image_text = (ImageView) converView.findViewById(R.id.image_id);

        result = converView;

        converView.setTag(viewHolder);
     else 
        viewHolder = (ViewHolder) converView.getTag();
        result = converView;
    

    viewHolder.name_text.setText(places.getName());
    Glide.with(getContext()).load(places.getImage()).into(viewHolder.image_text);

    return converView;

第二个活动,我传递数据的地方:

public class Card_activity extends AppCompatActivity implements View.OnClickListener

    TextView mTextView;

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

        mTextView = findViewById(R.id.head_name);
        String name = getIntent().getStringExtras("name")
        mTextView.setText(name);


已编辑:错误

java.lang.NullPointerException:尝试调用虚拟方法 空对象上的“java.lang.Object java.util.ArrayList.get(int)” 参考

在这一行:

Places places = randomPlaceList.get(position);

错误:

进程:com.example.eugene.lafinalproduction,PID:8352 java.lang.IllegalArgumentException: n

这一行的问题:

randomPlaceList.add(placesList.get(randomGenerator.nextInt(placeCount)));

【问题讨论】:

错误在哪里抛出?还添加错误堆栈跟踪 已添加。@PierGiorgioMisley 哪一行抛出 NPE? 在问题底部添加@Code-Apprentice 【参考方案1】:

该错误意味着您的randomPlaceList 为空。

由于我看不到应用程序或您为得到错误而执行的逻辑,所以我只是根据我看到的内容进行。

第一件事是,如果您需要获取点击的项目,应该通过调用adaptergetItem(position) 方法来完成;你可以像下面这样轻松地实现它:

@Override
public Places getItem(int position) 
    if(dataSet != null && position < dataSet.size())
       return dataSet.get(position);
    
    return null;

现在您可以从您的activity 执行如下调用:

Places places = mAdapter.getItem(position);

记得在初始化 adapter 时添加对它的引用,方法是在活动变量中添加 PlaceAdapter mAdapter; 并将初始化替换为

mAdapter = new PlaceAdapter(randomPlaceList, getBaseContext());
mListView.setAdapter(mAdapter);  

快速阅读代码,我对此也没有多大意义:

this.randomPlaceList = randomPlaceList;

但也许你删掉了一些代码,但我更愿意向你报告,以防万一:)


注意指明错误

错误在这里,它是关于变量引用:

        query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() 
            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) 
                if (task.isSuccessful()) 
                    List<Places> placesList = new ArrayList<>();
                    for (DocumentSnapshot document : task.getResult()) 
                        Places place = document.toObject(Places.class);
                        placesList.add(place);
                                          
                    int placeCount = placesList.size();
                    Random randomGenerator = new Random();  

                    // In the line below, you specify a new ArrayList that is LOCAL, you don't refer to the Activity's object
                    ArrayList<Places> randomPlaceList = new ArrayList<>();
                    for (int i = 1; i <= 3; i++) 
                        randomPlaceList.add(placesList.get(randomGenerator.nextInt(placeCount)));
                    
                    ListView mListView = (ListView) findViewById(R.id.place_list);
                    PlaceAdapter placeAdapter = new PlaceAdapter(randomPlaceList, getBaseContext());
                    mListView.setAdapter(placeAdapter);                    
            
        );

您应该将其替换为:

        query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() 
            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) 
                if (task.isSuccessful()) 
                    List<Places> placesList = new ArrayList<>();
                    for (DocumentSnapshot document : task.getResult()) 
                        Places place = document.toObject(Places.class);
                        placesList.add(place);
                                          
                    int placeCount = placesList.size();
                    Random randomGenerator = new Random();

                    randomPlaceList = new ArrayList<>(); //this is the activity's list
                    for (int i = 1; i <= 3; i++) 
                        randomPlaceList.add(placesList.get(randomGenerator.nextInt(placeCount)));
                    
                    ListView mListView = (ListView) findViewById(R.id.place_list);
                    PlaceAdapter placeAdapter = new PlaceAdapter(randomPlaceList, getBaseContext());
                    mListView.setAdapter(placeAdapter);                    
            
        );

否则活动的列表将永远为空,因为你从来没有初始化它

希望对你有帮助

【讨论】:

我使用了你答案的第一部分,它有帮助,答案的第二部分使OnItemClickListener方法全部变红,所以我没有用你说的local refer替换行。@Pier乔治·米斯利 我编辑了一个 Main Activity 类,现在可以使用了。@Pier Giorgio Misley 非常感谢,你帮了我很多忙!@Pier Giorgio Misley @SpikeJohnson 很高兴它帮助了你!如果您有更多问题,我/我们在这里 :) @SpikeJohnson 是的,我写它只是为了更好地说明错误的原因,但第一种方法可能更好^^【参考方案2】:

ListViewPlacesonCreate 方法中初始化您的randomPlaceList

randomPlaceList = new ArrayList<>();

目前您正在以这种方式初始化您的randomPlaceList this.randomPlaceList = randomPlaceList; 这是错误的,因为您正在分配 randomPlaceList 的相同副本,就像 a = a

并删除 ArrayList&lt;Places&gt; randomPlaceList = new ArrayList&lt;&gt;(); 内部的局部变量 query.get().addOnCompleteListener();

getIntent().getExtras() 返回一个 Bundle,它的值是 Key-Value 对(您可以将 Key-Value 对的多个值添加到 Bundle),但是您没有传递Bundle,你只是传递了一对Key-Value。所以最好在你的Card_activity中调用getStringExtra("name")

String name = getIntent().getStringExtra("name");

代替

String name = getIntent().getExtras().getString("name");

【讨论】:

一直以来都是错误,早在 RecycleView 中都使用 .getExtras.getString。我有问题。@Ghulam Moinul Quadir @SpikeJohnson 我已经更新了我的答案。我认为这可能会有所帮助 同一个地方出现同样的错误@Ghulam Moinul Quadir【参考方案3】:

在你的第二个活动中,改变这个:

String name = getIntent().getExtras().getString("name");

收件人:

String name = getIntent().getStringExtra("name");

【讨论】:

这是一直以来的错误,在 RecycleView 的早期,都使用 .getExtras.getString。我提出了错误。@Lucas Arrefelt 虽然第二个可能是首选,但它只是第一个的简写。这两行代码做的事情完全相同,不会修复错误。【参考方案4】:

您的代码中有几个问题。但是,让我们只关注您的问题。 你应该使用

intent.getStringExtra 

从以前的活动中获取字符串数据,而不是使用

intent.getExtras().getString("name");

getStringExtra 和 getExtras 是不同的。

【讨论】:

一直以来都是错误,在 RecycleView 的早期,所有都与 .getExtras.getString 一起工作。我提出了错误。@Chauyan 两者都做同样的事情。 我认为对于那个异常,你应该是 randomPlaceList 是否为空,如果这个变量不为空,你应该再次检查它的大小以避免索引超出边界异常@SpikeJohnson

以上是关于无法从 ListView 通过 Intent 正确传递数据的主要内容,如果未能解决你的问题,请参考以下文章

如何获取listView位置值并通过intent传递给另一个类

无法通过使用 Volley 库中的 Intent 从片段中移动下一个 Activity

尝试将数据从Intent迁移到ListView,但出现了一些错误

自定义 ListView 以处理从另一个 Intent 传递的 EditText 和 TextView

从 ListView 中选择一个蓝牙设备并打开一个新的 Intent (Android)

如何从自定义 ListView 适配器传递 Intent Extra?