【问题标题】:ArrayList / ArrayAdapter .add() function overwriting last element instead of adding to end of arrayArrayList / ArrayAdapter .add() 函数覆盖最后一个元素而不是添加到数组的末尾
【发布时间】:2016-02-05 18:25:28
【问题描述】:

我正在处理一项学校作业,即创建一个带有 2 个活动的书签应用程序,一个名为 BookNote 的 ListActivity 和一个名为 ManageActivity 的活动。

所有输入都必须在 ManageActivity 中完成并传回 BookNote 以进行列表更改、读取和写入数据。

我的问题是当我在 BookNote 活动中调用函数“addBookmark”时。我想要发生的是在列表末尾添加一个新列表项,其中包含书签对象信息。

发生的情况是列表末尾的任何项目都被简单地覆盖,而不是创建一个新项目。

下面是我的代码,cmets 说明了我对每个函数的意图。

BookNote 活动

public class BookNote extends ListActivity{
    private ArrayAdapter<Bookmark> adapter;
    private final String FILENAME = "bookmarks.txt";
    public String title = "EMPTY", url = "EMPTY", note = "EMPTY";
    public String bookmarkClicked ="";
    public int listViewID = 0;
    public boolean intentListener = false;
    public int intentReturnCounter = 0;
    public boolean addBookmarkClicked = false;
    public ArrayList<Bookmark> bookmarkList;


    /*When activity is called, list is populated by readData(), addBookmarkClicked is reset to false, intentLister is changed to true if returning from ManageActivity,
      if intentListener is true, addBookmarkClicked will be changed to true if AddBookmark is clicked from the BookNote menubar, a bookmark object will be created with information
       passed back from ManageActivity, and if addBookmarkClicked is true, the bookmark object will be added to the end of the list, otherwise it will be inserted in the same
       list element from which was chosen to edit.*/
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


        bookmarkList = readData();
        adapter = new ArrayAdapter<Bookmark>(this, android.R.layout.simple_list_item_1, bookmarkList);
        setListAdapter(adapter);

        addBookmarkClicked = false;
        intentListener = false;



            intentListener = getIntent().getBooleanExtra("listen", false);

            if (intentListener == true) {
                addBookmarkClicked = getIntent().getExtras().getBoolean("addBookmarkClicked", false);
                title = getIntent().getExtras().getString("title");
                url = getIntent().getExtras().getString("url");
                note = getIntent().getExtras().getString("note");
                listViewID = getIntent().getExtras().getInt("listViewID");
                Bookmark bookmark = new Bookmark(title, url, note);
                Toast.makeText(getApplicationContext(), "Intent return: True", Toast.LENGTH_SHORT).show();
                intentListener = false;

                if (addBookmarkClicked == true) {
                    addBookmark(bookmark);
                    Toast.makeText(getApplicationContext(), "Bookmark Added", Toast.LENGTH_SHORT).show();
                    addBookmarkClicked = false;
                } else {
                    insertBookmark(bookmark, listViewID);
                    Toast.makeText(getApplicationContext(), "Bookmark Edited", Toast.LENGTH_SHORT).show();
                }
                //writeData();
        }
    }



    //reads data when app runs and fills arrayadapter and list with items saved to bookmarks.txt
    private ArrayList<Bookmark> readData(){
        ArrayList<Bookmark> bookmarks = new ArrayList<>();

        try {
            FileInputStream fis = openFileInput(FILENAME);
            Scanner scanner = new Scanner(fis);
            if (scanner.hasNext()){
                String titleScan = scanner.nextLine();
                String urlScan = scanner.nextLine();
                String noteScan = scanner.nextLine();
                Bookmark bookmark = new Bookmark(titleScan, urlScan, noteScan);
                bookmarks.add(bookmark);
            }else{
                Bookmark bookmark = new Bookmark("Example Title", "Example URL", "Example Note");
                bookmarks.add(bookmark);
            }
            scanner.close();
        } catch (FileNotFoundException e) {
        }
        return bookmarks;
    }

    private void writeData(){
        try {
            FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
            OutputStreamWriter osw = new OutputStreamWriter(fos);
            BufferedWriter bw = new BufferedWriter(osw);
            PrintWriter pw = new PrintWriter(bw);

            for(int i = 0; i < adapter.getCount(); i++){
                Bookmark bookmark = adapter.getItem(i);
                pw.println(bookmark.getTitle() + "\n" + bookmark.getUrl() + "\n" + bookmark.getNote());
            }
            pw.close();
        } catch (FileNotFoundException e) {
            Log.e("Write ERR", "Cannot save: " + e.getMessage());
            e.printStackTrace();
            Toast.makeText(BookNote.this, "Error saving", Toast.LENGTH_SHORT).show();
        }
    }

    //If addBookmark menu item is clicked, this will be called to add a bookmark to the end of the ArrayAdapter.
    private void addBookmark(Bookmark bookmark){
        adapter.add(bookmark);
        writeData();
    }


    //Calls ManageActivity and reports information about app.
    public void gotoManageActivity(boolean addBookmarkClicked){
        Intent manageIntent = new Intent(this, ManageActivity.class);
        Bundle extras = new Bundle();
        extras.putString("bookmark", bookmarkClicked);
        extras.putBoolean("addBookmarkClicked", addBookmarkClicked);
        extras.putInt("listViewID", listViewID);
        manageIntent.putExtras(extras);
        startActivity(manageIntent);
    }



    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_add) {
            addBookmarkClicked = true;
            gotoManageActivity(addBookmarkClicked);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

管理活动

public class ManageActivity extends AppCompatActivity {

    private String title = "EMPTY", url = "EMPTY", note = "EMPTY";
    private boolean listener = true;
    private boolean addBookmarkClicked = false;



/* When activity starts, check for addBookmarkClicked status, create book */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.manage_layout);

        addBookmarkClicked = getIntent().getExtras().getBoolean("addBookmarkClicked", false);

        String bookmarkString = "";
        bookmarkString = getIntent().getExtras().getString("bookmark");
        if(bookmarkString != null && bookmarkString.length() > 0) {
            if (bookmarkString.length() != 0) {
                String[] stringArray = bookmarkString.split("\\n");
                title = stringArray[0];
                url = stringArray[1];
                note = stringArray[2];
                updateTextViews();
            }
        }
        else { updateTextViews();
        }
    }

    @Override
    public void onBackPressed(){
        Intent bookNoteIntent = new Intent(this, BookNote.class);
        Bundle extras = new Bundle();

        if(title.length() == 0 || title == null){title= "Empty";}
        if(url.length() == 0 || url == null){ url = "Empty";}
        if(note.length() == 0 || url == null) { note = "Empty";}

        extras.putString("title", title);
        extras.putString("url", url);
        extras.putString("note", note);
        extras.putBoolean("listen", listener);
        extras.putBoolean("addBookmarkClicked", addBookmarkClicked);
        bookNoteIntent.putExtras(extras);
        startActivity(bookNoteIntent);
    }

【问题讨论】:

  • 为什么你在onBackPressed开始BookNote活动???只需按“后退”按钮,您将转到该活动
  • 您提供了近 400 行代码。请将其减少为minimal reproducible example
  • @pskink 只是使用 to 来传回信息,而不是编写一个新函数来这样做。
  • 通过startActivityForResult 启动第二个活动传递回信息,请参阅文档了解其工作原理
  • 您能否将您的代码缩减为添加数据所需的代码?

标签: java android arraylist android-arrayadapter listactivity


【解决方案1】:

好问题!几周前,我也不得不自己处理这个问题。

主要是您需要重新实例化您的 ArrayAdapteradapter 在您的情况下。

现在你正确地做了第​​一步:

bookmarkList = readData();
adapter = new ArrayAdapter<Bookmark>(this, android.R.layout.simple_list_item_1, bookmarkList);
setListAdapter(adapter);

但是在尝试更新列表时您会再次执行此操作:我相信您正确添加了新书签,但您需要为列表视图重新创建 ArrayAdapter。

编辑: 我相信我发现了危险。 正如我之前提到的,在这里您需要重新实例化 ArrayAdapter。

private void addBookmark(Bookmark bookmark){
    adapter.add(bookmark);
    writeData();
}

基本上,每当您更新要显示在列表中的数据时,您都需要执行此步骤...

【讨论】:

  • 我尝试将以下内容添加到 addBookmark() 但仍然得到相同的结果 adapter = new ArrayAdapter&lt;Bookmark&gt;(this, android.R.layout.simple_list_item_1, bookmarkList); setListAdapter(adapter); adapter.add(bookmark); 我误解你了吗?
  • 我认为你应该将书签添加到书签列表中,然后执行adapter = new ArrayAdapter&lt;Bookmark&gt;(this, android.R.layout.simple_list_item_1, bookmarkList);setListAdapter(adapter);
  • 这样做只会将 2 个重复项添加到列表中,并且每当我尝试添加一个新项时,它都会用 2 个新重复项覆盖 2 个重复项。我按照您的建议在其余部分之前添加了bookmarkList.add(bookmark);
  • 请注意,没有必要按照您的建议创建新的 ArrayAdapter 对象。但是,需要将新元素添加到适配器使用的 ArrayList 中。当然,这可以通过简单地再次读取整个文件来完成。
  • 我在 addBookmark() 中将 bookmarkList.add(bookmark); 更改为 bookmarkList = readData();,这消除了重复的条目,但我仍然遇到最后一项被覆盖的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-28
  • 1970-01-01
  • 1970-01-01
  • 2013-07-15
  • 2017-09-18
  • 2012-12-02
相关资源
最近更新 更多