从 Android 应用打印日记条目

Posted

技术标签:

【中文标题】从 Android 应用打印日记条目【英文标题】:Printing out diary entries from Android app 【发布时间】:2021-09-24 02:52:04 【问题描述】:

我有一个关于 android 日记应用的简短问题。我正在尝试实现一个功能,用户单击应用程序上的“显示条目”按钮,它会显示以前插入数据库的所有日记条目。 '

首先用户登录应用程序,用户名/密码存储在数据库中。从那里,用户可以单击“创建条目”按钮以实际输入日期/日记条目。不幸的是,这是应用程序被挂起的地方,它实际上并没有将日期和日记条目插入数据库。

具体来说,它会挂在 diaryEntry() 中的 DataBaseHelper 类中,它会尝试将值输入到表中

long result = db.insert(TABLE_NAME, null, values);

result 返回 2,因此该调用下面的条件返回 true,但两个字符串都没有输入到数据库中的 COL_4 和 COL_5 中。我一直在扯我的头发试图抓住我错过的东西,但我没有看到它。我可以借一两个大脑袋来提供一些指点吗?谢谢!

日记主页面

public class DiaryMain extends AppCompatActivity 
    private Button showEntries;
    private DataBaseHelper myDB;

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

        showEntries = findViewById(R.id.showDiaryEntriesBtn);
        myDB = new DataBaseHelper(this);
    

    public void createEntryOnClick(View view) 
        Intent entryClick = new Intent(this, DiaryEntry.class);
        startActivity(entryClick);
    

    public void showEntriesOnClick() 

        showEntries.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                Cursor res = myDB.getData();

                if (res.getCount() == 0)
                    Toast.makeText(DiaryMain.this, "No entries", Toast.LENGTH_SHORT).show();
                    return;
                

                StringBuffer buffer = new StringBuffer();

                while (res.moveToNext()) 
                    buffer.append("Date: " + res.getString(0) + "\n");
                    //buffer.append("Entry: " + res.getString(1) + "\n");
                

                Toast.makeText(getApplicationContext(), buffer.toString(), Toast.LENGTH_LONG).show();
                
            
        );
    

日记输入意图

public class DiaryEntry extends AppCompatActivity 

    EditText date, diaryEntry;
    Button createBtn;
    private DataBaseHelper myDB;

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

        date = findViewById(R.id.dateField);
        diaryEntry = findViewById(R.id.entryField);
        createBtn = findViewById(R.id.diaryEntryBtn);

        myDB = new DataBaseHelper(this);

        createEntry();
    

    private void createEntry() 
        createBtn.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                String passDate = date.getText().toString();
                String passEntry = diaryEntry.getText().toString();

                boolean var = myDB.diaryEntry(passDate, passEntry);

                if (var)
                    Toast.makeText(DiaryEntry.this, "Entry posted!", Toast.LENGTH_SHORT).show();
                 else 
                    Toast.makeText(DiaryEntry.this, "Posting error", Toast.LENGTH_SHORT).show();
                
            
        );
    



还有数据库助手

public class DataBaseHelper extends SQLiteOpenHelper 

    private static final String DATABASE_NAME = "USER_RECORD";
    private static final String TABLE_NAME = "USER_DATA";
    private static final String COL_1 = "ID ";
    private static final String COL_2 = "USERNAME";
    private static final String COL_3 = "PASSWORD";
    private static final String COL_4 = "DATE";
    private static final String COL_5 = "ENTRY";

    public DataBaseHelper(@Nullable Context context) 
        super(context, DATABASE_NAME, null, 1);
    

    @Override
    public void onCreate(SQLiteDatabase db) 
        db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(ID INTEGER PRIMARY KEY AUTOINCREMENT, USERNAME TEXT, PASSWORD TEXT, DATE TEXT, ENTRY TEXT)");
    

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
        db.execSQL( "DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
    

    public boolean registerUser(String username, String password) 
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();

        values.put(COL_2, username);
        values.put(COL_3, password);

        long result = db.insert(TABLE_NAME, null, values);

        if (result == -1) 
            return false;
         else 
            return true;
        
    

    public boolean diaryEntry(String date, String diaryText) 
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();

        values.put(COL_4, date);
        values.put(COL_5, diaryText);

        long result = db.insert(TABLE_NAME, null, values);

        if (result == -1) 
            return false;
         else 
             return true;
        

    

    public Cursor getData() 
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery("SELECT * FROM USER_DATA", null);
        return cursor;
    

编辑:阅读文档,似乎 db.insert() 将行插入到数据库中,所以我是否走在正确的轨道上,因为我需要创建一个单独的表来插入日期/日记条目对?

【问题讨论】:

应用会崩溃吗? 不,它只是回到那个主要的日记意图。调试它,我可以看到它正在将条目收集为字符串并存储局部变量,但它只是没有将它们踢到 SQLite 表中。我……想……我可能需要数据库中的两个单独的表,因为它可能会尝试将一行插入到第一行已由用户名/密码组合填充的表中。 【参考方案1】:

dairyEntry 将插入用户名和密码行作为空值的数据。然而。当您问我是否会走在正确的轨道上,因为我需要创建一个单独的表来插入日期/日记条目对?然后是的。

也就是说,每个用户只需要一行(日期和条目不需要在 USER_DATA 表中),因为每个条目都会重复数据。

我建议使用 USER_DATA 表构建:-

db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(ID INTEGER PRIMARY KEY, USERNAME TEXT, PASSWORD TEXT)");
AUTOINCREMENT 已删除,因为它没有必要,效率低下。 已删除 DATE 和 ENTRY 列。

然后您将拥有第二个包含 3 列的表格。 DATE 和 ENTRY 以及一个用于引用用户 ID(不是 PRIMARY 键)的 INTEGER 列。无论如何都有一个 INTEGER PRIMARY KEY 列(可能没有命名为 ID)不会有什么坏处(只是它通常是隐藏的)。

举个例子

CREATE TABLE IF NOT EXISTS  diary_entry (id INTEGER PRIMARY KEY, date TEXT, entry TEXT, user_map INTEGER REFERENCES USER_DATA(id) ON DELETE CASCADE ON UPDATE CASCADE);
REFERENCES 定义了一个外键(基本上是一条规则,规定 user_map 列必须是现有用户的 id) ON DELETE CASCADE 将在用户被删除时删除所有行(即,它级联删除,因此没有孤立的 Dairy_entry 行) 在 UPDATE 时会将所做的任何更新传递给用户的 ID(不太可能)。

所以在插入条目时,diaryEntry 方法会略有不同:-

public boolean diaryEntry(long userid, String date, String diaryText) 
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues values = new ContentValues();

    values.put(COL_4, date);
    values.put(COL_5, diaryText);
    values.put("user_map",userid);

    return (db.insert(TABLE_NAME, null, values) > 0)
    

getAll 可能会基于如下查询:-

"SELECT diary_entry.*, USER_DATA.USERNAME, USER_DATA.PASSWORD FROM diary_entry JOIN USER_DATA ON diary_entry.user_map = USER_DATA.id;"
请注意,光标将包含列:- id(diary_entry 行的id) 日期 条目 user_map(与用户id相同) 用户名 密码

以上代码未经编译、运行或测试,可能存在拼写错误,为原则性代码

工作示例/演示

下面通过添加一些测试数据(2 个用户和 5 个日记条目)并在 ListView 中显示日记条目,将上述内容付诸实践(即 DatabaseHelper 代码),其中包括在这种情况下单击列表项的处理它是 Toast 的一些重新分级条目的信息(日记条目的 id 和用户名)。

第一个DatabaseHelper:-

public class DataBaseHelper extends SQLiteOpenHelper 

    /*
        Can be useful to have names available elsewhere (e.g. some are used in MainActivity)
     */
    public static final String DATABASE_NAME = "USER_RECORD";
    public static final String TABLE_NAME = "USER_DATA";
    public static final String ENTRY_TABLE_NAME = "diary_entry";
    //public static final String COL_1 = "ID "; /* Cursor Adapters MUST HAVE _id column so replaced by next line */
    public static final String COL_1 = BaseColumns._ID; /* Cursor Adapter expects _id column name */
    public static final String COL_2 = "USERNAME";
    public static final String COL_3 = "PASSWORD";
    public static final String COL_4 = "DATE";
    public static final String COL_5 = "ENTRY";
    public static final String COl_6 = "user_map";

    private SQLiteDatabase db; // saves having to use getWritableDatabase all the time */

    public DataBaseHelper(@Nullable Context context) 
        super(context, DATABASE_NAME, null, 1);
        db = this.getWritableDatabase(); // Forces an open of the database
    

    @Override
    public void onCreate(SQLiteDatabase db) 
        db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" +
                COL_1 + " INTEGER PRIMARY KEY," +
                COL_2 + " TEXT," +
                COL_3 + " TEXT" +
                ")"
        );
        db.execSQL("CREATE TABLE IF NOT EXISTS " + ENTRY_TABLE_NAME + "(" +
                COL_1 + " INTEGER PRIMARY KEY, " +
                COL_4 + " TEXT, " +
                COL_5 + " TEXT, " +
                COl_6 + " INTEGER REFERENCES " + TABLE_NAME + "(" + /* Included for ListView */
                COL_1 +
                ") ON DELETE CASCADE ON UPDATE CASCADE " +
                ")"
        );
    

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
        db.execSQL( "DROP TABLE IF EXISTS " + TABLE_NAME);
        db.execSQL("DROP TABLE IF EXISTS " + ENTRY_TABLE_NAME); /* ADDED */
        onCreate(db);
    

    public boolean registerUser(String username, String password) 
        //SQLiteDatabase db = this.getWritableDatabase(); // no need now
        ContentValues values = new ContentValues();
        values.put(COL_2, username);
        values.put(COL_3, password);
        return db.insert(TABLE_NAME, null, values) > 0;
        /* Simpler return used
        if (result == -1) 
            return false;
         else 
            return true;
        
         */
    

    /*
        This version returns the id of the inserted user (can be useful)

     */
    public long otherReqisterUser(String userName, String password) 
        ContentValues values = new ContentValues();
        values.put(COL_2,userName);
        values.put(COL_3,password);
        return db.insert(TABLE_NAME,null,values);
    

    public boolean diaryEntry(Long userid, String date, String diaryText) 
        //SQLiteDatabase db = this.getWritableDatabase(); // not needed now
        ContentValues values = new ContentValues();
        values.put(COl_6,userid);
        values.put(COL_4, date);
        values.put(COL_5, diaryText);
        return db.insert(ENTRY_TABLE_NAME, null, values) > 0;
    

    /*
    public Cursor getData() 
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery("SELECT * FROM USER_DATA", null);
        return cursor;
    
     */

    public Cursor getData() 
        /* rather than rawQuery query convenience method is recommended
           However, this one is a little complex now due to Join
         */

        /* The following is the equivalent of :-
            SELECT diary_entry.*, USER_DATA.USERNAME, USER_DATA.PASSWORD
            FROM diary_entry
            JOIN USER_DATA ON diary_entry.user_map = USER_DATA.id
            ORDER BY USER_DATA._id ASC, diary_entry.date
            ;
         */
        return db.query(
                /* Although doco says this arg is table it is actually the FROM clause so JOIN's go here*/
                ENTRY_TABLE_NAME + " JOIN " + TABLE_NAME + " ON " + ENTRY_TABLE_NAME + "." + COl_6 + "=" + TABLE_NAME + "." + COL_1,
                /* The columns as a String[] */
                new String[]ENTRY_TABLE_NAME + ".*",TABLE_NAME + "." + COL_2, TABLE_NAME + "." + COL_3,
                /* no WHERE clause, no bound parameters (?), no GROUP BY clause, no HAVING clause*/
                null,null,null,null,
                /* However ORDER BY clause by user then by date */
                TABLE_NAME+"."+COL_1+" ASC," + ENTRY_TABLE_NAME + "." + COL_4 + " ASC"
                );
    

还有 MainActivity :-

public class MainActivity extends AppCompatActivity 

    DataBaseHelper db;
    Cursor csr;
    SimpleCursorAdapter sca;
    ListView lv;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lv = this.findViewById(R.id.diaryentries); /* List View from layout */
        db = new DataBaseHelper(this);

        /* Add data if none exists */
        if (DatabaseUtils.queryNumEntries(db.getWritableDatabase(),DataBaseHelper.TABLE_NAME)< 1) 
            /* Add some testing users */
            long fredsId = db.otherReqisterUser("FRED", "password");
            long marysId = db.otherReqisterUser("MARY", "password");
            /* Add some diary entries */
            db.diaryEntry(fredsId, "2021-01-01", "Got up (Fred)");
            db.diaryEntry(marysId, "2021-01-01", "Got up (Mary)");
            db.diaryEntry(fredsId, "2021-01-02", "Went to work (Fred)");
            db.diaryEntry(marysId, "2021-02-02", "Was sick.(Mary)");
            db.diaryEntry(fredsId,"1999-01-01","Ooosps wasn't around!!!!");
        

        DatabaseUtils.dumpCursor(csr = db.getData());
        setupOrRefreshListView(); // setup the ListView

    

    private void setupOrRefreshListView() 
        csr = db.getData();
        if (sca == null) 
            sca = new SimpleCursorAdapter(
                    this,
                    android.R.layout.simple_list_item_2,csr,
                    new String[]
                            DataBaseHelper.COL_4,
                            DataBaseHelper.COL_5
                    ,
                    new int[]
                            android.R.id.text1,
                            android.R.id.text2
                    ,
                    0
            );
            lv.setAdapter(sca);
            lv.setOnItemClickListener(new AdapterView.OnItemClickListener() 
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) 
                    Toast.makeText(view.getContext(),
                            "You clicked on Diary Entry id = " + String.valueOf(l) +
                                    " for " + csr.getString(csr.getColumnIndex(DataBaseHelper.COL_2)),
                            Toast.LENGTH_LONG)
                            .show();
                
            );
         else 
            sca.swapCursor(csr);
        
    

    @Override
    protected void onDestroy() 
        super.onDestroy();
        if(!csr.isClosed()) 
            csr.close();
        
    

希望 cmets 解释一下。

结果

应用程序运行时的样子:-

点击一个条目(Fred Got Up 被点击)并且:-

【讨论】:

绝对完美,这正是我需要阅读的内容。我会在早上试一试,因为我的头被炸了。谢谢你的好建议! @ZapRowsdower 正在使用上面的示例/演示进行工作,因此将检查代码。很快就会更新答案。 在您之前的回答之后不久,我再次愚弄了它,并实施了第二个表格,但它仍然没有将文本推送到第二个表格。我将尝试实现这些字段更改,看看我是否可以让这个东西正常工作。另外,非常感谢您缩减 getData() 函数;我试图让它只拉动所有东西,但是通过我们的 cmets,我看到了它的流程现在应该如何工作。作为旁注,有没有办法点击一个条目来编辑内容?无论如何,绝对的黄金我的朋友,再次感谢! @ZapRowsdower 添加了另一个答案,这实现了单击以编辑条目而不是 Toast。【参考方案2】:

关于评论:-

顺便说一句,有没有办法点击一个条目来编辑内容?无论如何,绝对的黄金我的朋友,再次感谢!

是的,很简单。将修改 DiaryEntry 活动以根据条目的 id(将其称为 entryId)接受数据,并在编辑时更新而不是插入而不是插入新的。

无论如何,您都需要修改 DairyEntry 以确定为其创建条目的用户。

但是,DatabaseHelper 也需要修改。它需要能够更新日记条目并根据 entryId 检索其他数据。

我做了一些其他的改变

因为 JOIN 将被多次使用,所以我添加了常量。 与要提取的列相同 由于 2 个 _id 列(USERDATE 和 DiaryEntry)之间存在歧义,因此 USERDATA 列被重命名(新名称为常量)

所以 DatabaseHelper 现在是:-

public class DataBaseHelper extends SQLiteOpenHelper 

    /*
        Can be useful to have names available elsewhere (e.g. some are used in MainActivity)
     */
    public static final String DATABASE_NAME = "USER_RECORD";
    public static final String TABLE_NAME = "USER_DATA";
    public static final String ENTRY_TABLE_NAME = "diary_entry";
    //public static final String COL_1 = "ID "; /* Cursor Adapters MUST HAVE _id column so replaced by next line */
    public static final String COL_1 = BaseColumns._ID; /* Cursor Adapter expects _id column name */
    public static final String COL_2 = "USERNAME";
    public static final String COL_3 = "PASSWORD";
    public static final String COL_4 = "DATE";
    public static final String COL_5 = "ENTRY";
    public static final String COl_6 = "user_map";
    public static final String DERIVED_USERID_COLUMN = "userid"; /*<<<<< ADDED used to disambiguate column names >>>>>*/


    /*<<<<< ADDED 2 constants for Join between Entry and User and for the columns >>>>>*/
    private static final String ENTRYTABLE_USERTABLE_JOIN = ENTRY_TABLE_NAME + " JOIN " + TABLE_NAME + " ON " + ENTRY_TABLE_NAME + "." + COl_6 + "=" + TABLE_NAME + "." + COL_1 + " ";
    private static final String[] ENTRYTABLE_USERTABLE_COLUMNS = new String[]
            ENTRY_TABLE_NAME + ".*",
            TABLE_NAME + "." + COL_1 + " AS " + DERIVED_USERID_COLUMN, /* give the USER _id column an alternative name using AS clause so there are not 2 _id columns */
            TABLE_NAME + "." + COL_2,
            TABLE_NAME + "." + COL_3
    ;

    private SQLiteDatabase db; // saves having to use getWritableDatabase all the time */

    public DataBaseHelper(@Nullable Context context) 
        super(context, DATABASE_NAME, null, 1);
        db = this.getWritableDatabase(); // Forces an open of the database
    

    @Override
    public void onCreate(SQLiteDatabase db) 
        db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" +
                COL_1 + " INTEGER PRIMARY KEY," +
                COL_2 + " TEXT," +
                COL_3 + " TEXT" +
                ")"
        );
        db.execSQL("CREATE TABLE IF NOT EXISTS " + ENTRY_TABLE_NAME + "(" +
                COL_1 + " INTEGER PRIMARY KEY, " +
                COL_4 + " TEXT, " +
                COL_5 + " TEXT, " +
                COl_6 + " INTEGER REFERENCES " + TABLE_NAME + "(" + /* Included for ListView */
                COL_1 +
                ") ON DELETE CASCADE ON UPDATE CASCADE " +
                ")"
        );
    

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
        db.execSQL( "DROP TABLE IF EXISTS " + TABLE_NAME);
        db.execSQL("DROP TABLE IF EXISTS " + ENTRY_TABLE_NAME); /* ADDED */
        onCreate(db);
    

    public boolean registerUser(String username, String password) 
        //SQLiteDatabase db = this.getWritableDatabase(); // no need now
        ContentValues values = new ContentValues();
        values.put(COL_2, username);
        values.put(COL_3, password);
        return db.insert(TABLE_NAME, null, values) > 0;
        /* Simpler return used
        if (result == -1) 
            return false;
         else 
            return true;
        
         */
    

    /* This version returns the id of the inserted user (can be useful) */
    public long otherReqisterUser(String userName, String password) 
        ContentValues values = new ContentValues();
        values.put(COL_2,userName);
        values.put(COL_3,password);
        return db.insert(TABLE_NAME,null,values);
    

    public boolean diaryEntry(Long userid, String date, String diaryText) 
        //SQLiteDatabase db = this.getWritableDatabase(); // not needed now
        ContentValues values = new ContentValues();
        values.put(COl_6,userid);
        values.put(COL_4, date);
        values.put(COL_5, diaryText);
        return db.insert(ENTRY_TABLE_NAME, null, values) > 0;
    

    /*<<<<< ADDED >>>>>*/
    public long updateDiaryEntry(long entryId, String date, String entry) 
        ContentValues values = new ContentValues();
        values.put(COL_4,date);
        values.put(COL_5,entry);
        return db.update(ENTRY_TABLE_NAME,values,COL_1 + "=?",new String[]String.valueOf(entryId));
    

    /*<<<<< ADDED >>>>>*/
    public Cursor getEntryById(long entryId) 
        return db.query(
                ENTRYTABLE_USERTABLE_JOIN,
                ENTRYTABLE_USERTABLE_COLUMNS,
                ENTRY_TABLE_NAME + "." + COL_1 + "=?",
                new String[]String.valueOf(entryId),
                null,null,null
        );
    

    /*
    public Cursor getData() 
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery("SELECT * FROM USER_DATA", null);
        return cursor;
    
     */

    public Cursor getData() 
        /* rather than rawQuery query convenience method is recommended
           However, this one is a little complex now due to Join
         */

        /* The following is the equivalent of :-
            SELECT diary_entry.*, USER_DATA.USERNAME, USER_DATA.PASSWORD
            FROM diary_entry
            JOIN USER_DATA ON diary_entry.user_map = USER_DATA.id
            ORDER BY USER_DATA._id ASC, diary_entry.date
            ;
         */
        return db.query(
                /* Although doco says this arg is table it is actually the FROM clause so JOIN's go here*/
                /*ENTRY_TABLE_NAME + " JOIN " + TABLE_NAME + " ON " + ENTRY_TABLE_NAME + "." + COl_6 + "=" + TABLE_NAME + "." + COL_1*/
                ENTRYTABLE_USERTABLE_JOIN, //<<<<< CHANGED to use constant as JOIN used elsewhere
                /* The columns as a String[] */
                ENTRYTABLE_USERTABLE_COLUMNS, //<<<<< CHANGED to use constant as columns used elsewhere
                /* no WHERE clause, no bound parameters (?), no GROUP BY clause, no HAVING clause*/
                null,null,null,null,
                /* However ORDER BY clause by user then by date */
                TABLE_NAME+"."+COL_1+" ASC," + ENTRY_TABLE_NAME + "." + COL_4 + " ASC"
                );
    

DiaryEntry 变为:-

public class DiaryEntry extends AppCompatActivity 

    public static final String INTENT_EXTRA_USERID = "userid";
    public static final String INTENT_EXTRA_ENTRYID = "entryid";

    EditText date, diaryEntry;
    Button createBtn, doneBtn;
    private DataBaseHelper myDB;
    private long entryId = -1, userId = -1;
    private String userName, password;


    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_diary_entry);
        // Get the entryId (if editing entry else should be -1) AND
        // the userId (MUST BE PROVIDED if ADDING will be retrieved when editing and Entry)
        entryId = this.getIntent().getLongExtra(INTENT_EXTRA_ENTRYID,-1);
        userId = this.getIntent().getLongExtra(INTENT_EXTRA_USERID,-1);

        date = findViewById(R.id.dateField);
        diaryEntry = findViewById(R.id.entryField);
        createBtn = findViewById(R.id.diaryEntryBtn);
        doneBtn = this.findViewById(R.id.done);
        myDB = new DataBaseHelper(this);
        // Id Entry ID provided then populate the Edit Texts
        if (entryId > 0) 
            Cursor csr = myDB.getEntryById(entryId);
            if (csr.moveToFirst()) 
                date.setText(csr.getString(csr.getColumnIndex(DataBaseHelper.COL_4)));
                diaryEntry.setText(csr.getString(csr.getColumnIndex(DataBaseHelper.COL_5)));
                userId = csr.getLong(csr.getColumnIndex(DataBaseHelper.DERIVED_USERID_COLUMN));
                userName = csr.getString(csr.getColumnIndex(DataBaseHelper.COL_2));
                password = csr.getString(csr.getColumnIndex(DataBaseHelper.COL_3));
            
            csr.close(); // ALWAYS close cursor when finished with them
        
        setupButtons();
    

    private void setupButtons() 
        doneBtn.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                finish();
            
        );
        createBtn.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                // MUST HAVE A VALID USERID IF NOT CANNOT ADD OR EDIT
                if (userId < 1) 
                    Toast.makeText(view.getContext(),"UNABLE TO PROCEED - NO KNOWN USER",Toast.LENGTH_SHORT).show();
                    return;
                
                if (entryId > 0) 
                    myDB.updateDiaryEntry(entryId,date.getText().toString(),diaryEntry.getText().toString());
                 else 
                    myDB.diaryEntry(userId,date.getText().toString(),diaryEntry.getText().toString());
                
            
        );
    

    /*
    private void createEntry() 
        createBtn.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                String passDate = date.getText().toString();
                String passEntry = diaryEntry.getText().toString();

                //boolean var = myDB.diaryEntry(passDate, passEntry);

                if (var)
                    Toast.makeText(DiaryEntry.this, "Entry posted!", Toast.LENGTH_SHORT).show();
                 else 
                    Toast.makeText(DiaryEntry.this, "Posting error", Toast.LENGTH_SHORT).show();
                
            
        );
    

     */

我已更改布局以添加完成按钮(尽管您可以编辑应用并返回)。我使用 createButton 进行应用(添加新条目或更新)。

插入后,您可能应该清除编辑文本,但主要是显示如何单击列表进行编辑,然后返回并更新列表。

很明显 MainActivity 已经改变了,但没那么大。它不是 toasting,而是构造一个 Intent 添加一个 Extra 来传递 entryId 并启动 DiaryEntry 活动。

Main Activity 的 onResume 方法已被覆盖以刷新 ListView。

:-

public class MainActivity extends AppCompatActivity 

    DataBaseHelper db;
    Cursor csr;
    SimpleCursorAdapter sca;
    ListView lv;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lv = this.findViewById(R.id.diaryentries); /* List View from layout */
        db = new DataBaseHelper(this);

        /* Add data if none exists */
        if (DatabaseUtils.queryNumEntries(db.getWritableDatabase(),DataBaseHelper.TABLE_NAME)< 1) 
            /* Add some testing users */
            long fredsId = db.otherReqisterUser("FRED", "password");
            long marysId = db.otherReqisterUser("MARY", "password");
            /* Add some diary entries */
            db.diaryEntry(fredsId, "2021-01-01", "Got up (Fred)");
            db.diaryEntry(marysId, "2021-01-01", "Got up (Mary)");
            db.diaryEntry(fredsId, "2021-01-02", "Went to work (Fred)");
            db.diaryEntry(marysId, "2021-02-02", "Was sick.(Mary)");
            db.diaryEntry(fredsId,"1999-01-01","Ooosps wasn't around!!!!");
        

        DatabaseUtils.dumpCursor(csr = db.getData());
        setupOrRefreshListView(); // setup the ListView

    

    private void setupOrRefreshListView() 
        csr = db.getData();
        if (sca == null) 
            sca = new SimpleCursorAdapter(
                    this,
                    android.R.layout.simple_list_item_2,csr,
                    new String[]
                            DataBaseHelper.COL_4,
                            DataBaseHelper.COL_5
                    ,
                    new int[]
                            android.R.id.text1,
                            android.R.id.text2
                    ,
                    0
            );
            lv.setAdapter(sca);
            lv.setOnItemClickListener(new AdapterView.OnItemClickListener() 
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) 
                    /*
                    Toast.makeText(view.getContext(),
                            "You clicked on Diary Entry id = " + String.valueOf(l) +
                                    " for " + csr.getString(csr.getColumnIndex(DataBaseHelper.COL_2)),
                            Toast.LENGTH_LONG)
                            .show();

                     */
                    /*
                        Clicking item takes it to the modified DiaryEntry passing the
                        entryId via the Intent.
                    */
                    Intent intent = new Intent(view.getContext(),DiaryEntry.class);
                    intent.putExtra(DiaryEntry.INTENT_EXTRA_ENTRYID,l);
                    startActivity(intent);
                
            );
         else 
            sca.swapCursor(csr);
        
    

    @Override
    protected void onResume() 
        super.onResume();
        setupOrRefreshListView();
    

    @Override
    protected void onDestroy() 
        super.onDestroy();
        if(!csr.isClosed()) 
            csr.close();
        
    

结果

开始时:-

点击进入:-

将文本更改为其实我在附近,然后点击应用:-

最后点击完成:-

【讨论】:

天哪,这正是我要找的。通读修改,这比我昨天大部分时间试图偶然发现的要有意义得多。再多谢一百万,我非常感谢您提供的所有帮助。

以上是关于从 Android 应用打印日记条目的主要内容,如果未能解决你的问题,请参考以下文章

Android 日记应用 - 搜索 SQLite 数据库并在 ListView 中显示结果

Android logcat:使用电子邮件从设备发送日志条目

android踩坑日记1

android从pdfview打印

Android studio课程设计开发实现---日记APP

Android 联系人:是不是可以使用 URN 引用给定的联系人条目?