【问题标题】:List View not updating beyond one item列表视图不更新超过一项
【发布时间】:2017-02-16 10:04:39
【问题描述】:

我正在尝试将列表中的一项发送到另一个活动的列表。但是第二个活动,即 MySchedule 不会更新超过一项。 这是我的代码

我发送字符串的活动 (没有添加字符串的代码)

public class CloudEvents extends AppCompatActivity {

    static int scheduleId = -1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
     listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {

                new AlertDialog.Builder(CloudEvents.this)
                        .setIcon(android.R.drawable.ic_dialog_alert)
                        .setTitle("Save Event")
                        .setMessage("Do you want to save this event into your schedule?")
                        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                            scheduleId++;

                                Toast.makeText(CloudEvents.this,"Saved",Toast.LENGTH_LONG).show();
                                SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("com.yatin.whatshappeningdtu", Context.MODE_PRIVATE);
                         sharedPreferences.edit().putString("CloudEvent",listView.getItemAtPosition(position).toString()).apply();
                                Intent i = new Intent(CloudEvents.this,MySchedule.class);
                                startActivity(i);


                               //myArrayAdapter.notifyDataSetChanged();
                            }
                        })
                        .setNegativeButton("No",null)
                        .show();

                return true;
            }
        });

Activity 接收字符串并制作列表

public class MySchedule extends AppCompatActivity {

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

    final ArrayList<String> schedule = new ArrayList<>();
    final ListView scheduleListView = (ListView)findViewById(R.id.scheduleListView);
    String key = "CloudEvent";

    String myEvent ="";

    SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("com.yatin.whatshappeningdtu", Context.MODE_PRIVATE);
    if(sharedPreferences.contains(key))
    {
        myEvent = sharedPreferences.getString(key,"");
        schedule.add(CloudEvents.scheduleId,myEvent);

    }
    final ArrayAdapter myArrayAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,schedule);

    scheduleListView.setAdapter(myArrayAdapter);

    scheduleListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {

            new AlertDialog.Builder(MySchedule.this)
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .setTitle("Are you sure ?")
                    .setMessage("Do you want to delete this note")
                    .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            schedule.remove(position);
                            myArrayAdapter.notifyDataSetChanged();
                            CloudEvents.scheduleId--;

                        }
                    })
                    .setNegativeButton("No",null)
                    .show();

            return true;
        }
    });

}
}

(添加一项后)

Error:Caused by: java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
                      at java.util.ArrayList.add(ArrayList.java:457)
                      at com.yatin.whatshappeningdtu.MySchedule.onCreate(MySchedule.java:35)

现在已经绞尽脑汁了好几个小时。请帮忙谢谢!

【问题讨论】:

  • 在将调度列表传递给阵列适配器之前检查其大小
  • CloudEvents.scheduleId 即使数组为空也会返回 1。所以理想情况下 ArrayList.add 应该将您的 String 添加到 '0' 位置。但是 CloudEvents.scheduleId 要求它将其添加到“0”位置,因此出现错误
  • 听不懂你想说什么:/

标签: android listview arraylist android-arrayadapter


【解决方案1】:

当您第一次添加项目时,您的 CloudEvents.scheduleId 会从 -1 设置为 0。假设你的字符串是"FirstEvent",保存在sharedpreference的CloudEvent键中,然后在MySchedule活动中添加到schedulearraylist的0位置,就可以正常工作了。

现在,当您回到CloudEvents 活动时,您的CloudEvents.scheduleId 为0,因为它是静态变量,并且您添加了另一个项目,比如说"SecondEvent",所以CloudEvents.scheduleId 将从0 变为1,您是将"SecondEvent" 字符串保存在CloudEvent 中的CloudEvent 键中再次在sharedpreference 中,以便先前的值"FirstEvent" 将被"SecondEvent" 覆盖,这意味着在MySchedule 活动中您将只能从sharedpreference 中获得"SecondEvent",但您将其添加到schedule arraylist 的第 1 个位置和 schedule arraylist 的第 0 个位置将保留为空。 现在您在 Listview 适配器中传递这个数组列表,第 0 位为空值,这就是它抛出 IndexOutOfBoundsException 异常的方式。 为了解决这个问题,您可以维护一个ArrayList&lt;String&gt;。在CloudEvents 活动中进行以下更改。

private ArrayList<String> eventList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState){

        SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("com.yatin.whatshappeningdtu", Context.MODE_PRIVATE);
        Collections.addAll(eventList, prefManager.getString("CloudEvent", "").split(","));

        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {

                new AlertDialog.Builder(CloudEvents.this)
                        .setIcon(android.R.drawable.ic_dialog_alert)
                        .setTitle("Save Event")
                        .setMessage("Do you want to save this event into your schedule?")
                        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                scheduleId++;

                                eventList.add(listView.getItemAtPosition(position).toString());
                                Toast.makeText(CloudEvents.this, "Saved", Toast.LENGTH_LONG).show();

                                Intent i = new Intent(CloudEvents.this, MySchedule.class);
                                i.putStringArrayListExtra("EventList", eventList);                                   
                                startActivity(i);

                                //myArrayAdapter.notifyDataSetChanged();
                            }
                        })
                        .setNegativeButton("No", null)
                        .show();

                return true;
            }
        });
    }

现在在MySchedule 活动中进行以下更改。

公共类 MySchedule 扩展 AppCompatActivity {

    ArrayList<String> schedule = new ArrayList<>();
    SharedPreferences sharedPreferences;

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

        sharedPreferences = getApplicationContext().getSharedPreferences("com.yatin.whatshappeningdtu", Context.MODE_PRIVATE);

        schedule = getIntent().getStringArrayListExtra("EventList");
        ListView scheduleListView = (ListView)findViewById(R.id.scheduleListView);

        final ArrayAdapter myArrayAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,schedule);

        scheduleListView.setAdapter(myArrayAdapter);

        scheduleListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {

                new AlertDialog.Builder(MySchedule.this)
                        .setIcon(android.R.drawable.ic_dialog_alert)
                        .setTitle("Are you sure ?")
                        .setMessage("Do you want to delete this note")
                        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                schedule.remove(position);
                                myArrayAdapter.notifyDataSetChanged();

                                String events = "";
                                for(int i=0; i<schedule.size(); i++){
                                    events = events + schedule.get(i);
                                    if(i != (schedule.size() - 1)){
                                        events = events + ",";
                                    }
                                }
                                sharedPreferences.edit().putString("CloudEvent", events).apply();
                            }
                        })
                        .setNegativeButton("No",null)
                        .show();

                return true;
            }
        });

    }
}

【讨论】:

  • 谢谢!终于明白了!你能建议我应该实施以使其工作的方法吗?
  • 检查我的编辑,我对您的代码做了一些更改,尚未测试,如果您仍然发现任何重大问题,请告诉我。
【解决方案2】:

试试 commit() 而不是 apply()

apply() 是在 2.3 中添加的,它提交时不返回指示成功或失败的布尔值。

commit() 如果保存成功则返回 true,否则返回 false。

另外请确认用于读取数据的共享偏好实例与写入数据的实例相同。

【讨论】:

  • 共享首选项正在传输数据没有问题,但列表没有更新项目(如果我删除 scheduleId++)它会不断更改第 0 个项目并且不会移动增加列表的大小
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-21
  • 2011-10-28
相关资源
最近更新 更多