Trang chủHướng dẫnHướng dẫn thực hành Android SQLite: Từ lý thuyết đến ứng dụng thực tế
Chuyên gia

Hướng dẫn thực hành Android SQLite: Từ lý thuyết đến ứng dụng thực tế

CyStack blog 11 phút để đọc
CyStack blog10/06/2025
Locker Avatar

Chris Pham

Technical Writer

Locker logo social
Reading Time: 11 minutes

Hướng dẫn thực hành Android SQLite

Chào mừng bạn đến với hướng dẫn chi tiết về cơ sở dữ liệu Android SQLite.

SQLite là phương thức lưu trữ dữ liệu phổ biến nhất trong các ứng dụng Android và là nền tảng của nhiều ứng dụng. Nó có thể được sử dụng trực tiếp hoặc thông qua một trình bao bọc của bên thứ ba. Dưới đây là ứng dụng được lập trình sử dụng cơ sở dữ liệu SQLite trong Android.


Android SQLite

Android SQLite là một cơ sở dữ liệu rất nhẹ đi kèm với hệ điều hành Android. Android SQLite sở hữu giao diện SQL rõ ràng với dung lượng bộ nhớ rất nhỏ và tốc độ khá mượt mà. Đối với Android, SQLite được “tích hợp sẵn” vào Android runtime, vì vậy mọi ứng dụng Android đều có thể tạo cơ sở dữ liệu SQLite của riêng mình. API gốc của Android SQLite không phải là JDBC vì JDBC tốn quá nhiều tài nguyên cho một điện thoại thông minh có bộ nhớ hạn chế. Khi cơ sở dữ liệu được tạo thành công, nó sẽ nằm trong thư mục data/data/<package_name>/databases/, có thể được truy cập từ Android Device Monitor. SQLite là một cơ sở dữ liệu quan hệ điển hình, chứa các bảng (gồm các hàng và cột), chỉ mục, v.v. Chúng ta có thể tạo các bảng riêng để chứa dữ liệu một cách phù hợp. Cấu trúc này được gọi là một lược đồ cơ sở dữ liệu (schema).

Android SQLite SQLiteOpenHelper

Android có các tính năng để xử lý việc thay đổi schema cơ sở dữ liệu. Tính năng này chủ yếu phụ thuộc vào việc sử dụng lớp SQLiteOpenHelper. SQLiteOpenHelper để giải quyết hai vấn đề rất phổ biến:

  1. Khi ứng dụng chạy lần đầu tiên: Tại thời điểm này, chúng ta chưa có cơ sở dữ liệu. Vì vậy, chúng ta sẽ phải tạo các bảng, chỉ mục, dữ liệu ban đầu, v.v.
  2. Khi ứng dụng được nâng cấp lên một schema mới hơn: Cơ sở dữ liệu của chúng ta vẫn sẽ ở schema cũ từ phiên bản trước đó của ứng dụng. Chúng ta sẽ có tùy chọn thay đổi schema cơ sở dữ liệu để phù hợp với nhu cầu của phần còn lại của ứng dụng.

SQLiteOpenHelper gói gọn các logic này để tạo và nâng cấp cơ sở dữ liệu theo các thông số kỹ thuật của chúng ta. Để làm được điều đó, chúng ta cần tạo một lớp con tùy chỉnh của SQLiteOpenHelper triển khai ít nhất ba phương thức sau:

  1. Constructor: Hàm này nhận Context (ví dụ: một Activity), tên của cơ sở dữ liệu, một cursor factory tùy chọn (chúng ta sẽ thảo luận sau), và một số nguyên đại diện cho phiên bản của schema cơ sở dữ liệu mà bạn đang sử dụng (thường bắt đầu từ 1 và tăng lên sau này).public DatabaseHelper (Context context) { super(context, DB_NAME, null, DB_VERSION); }
  2. onCreate(SQLiteDatabase db): Phương thức này được gọi khi không có cơ sở dữ liệu có sẵn và ứng dụng cần một cơ sở dữ liệu để xử lý. Nó chuyển cho chúng ta một object SQLiteDatabase, trỏ đến một cơ sở dữ liệu mới được tạo. Chúng ta có thể điền các bảng và dữ liệu ban đầu vào cơ sở dữ liệu mới này.
  3. onUpgrade (SQLiteDatabase db, int oldVersion, int newVersion): Phương thức này được gọi khi phiên bản schema chúng ta cần không khớp với phiên bản schema của cơ sở dữ liệu. Nó chuyển đến một object SQLiteDatabase và các số phiên bản cũ và mới. Nhờ đó, chúng ta có thể tìm ra cách tốt nhất để chuyển đổi cơ sở dữ liệu từ schema cũ sang schema mới.

Cần định nghĩa thêm một lớp DBManager để thực hiện tất cả các thao tác CRUD (Tạo, Đọc, Cập nhật và Xóa) cơ sở dữ liệu.

Thực hành Android SQLite

 

Mở và Đóng Kết nối Cơ sở dữ liệu Android SQLite

Trước khi thực hiện bất kỳ thao tác cơ sở dữ liệu nào như chèn, cập nhật, xóa bản ghi trong bảng, trước tiên hãy mở kết nối cơ sở dữ liệu bằng cách gọi phương thức getWritableDatabase() như sau:

Java

public DBManager open() throws SQLException { dbHelper = new DatabaseHelper(context); database = dbHelper.getWritableDatabase(); return this; }

dbHelper là một instance của lớp con SQLiteOpenHelper. Để đóng kết nối cơ sở dữ liệu, gọi phương thức sau:

Java

public void close() { dbHelper.close(); }

Chèn bản ghi mới vào bảng cơ sở dữ liệu Android SQLite

Đoạn code sau đây hướng dẫn cách chèn một bản ghi mới vào cơ sở dữ liệu Android SQLite.

Java

public void insert(String name, String desc) { ContentValues contentValue = new ContentValues(); contentValue.put(DatabaseHelper.SUBJECT, name); contentValue.put(DatabaseHelper.DESC, desc); database.insert(DatabaseHelper.TABLE_NAME, null, contentValue); }

ContentValues tạo một tập hợp giá trị trống. Tôi sẽ nói thêm về các giá trị instance khác khi đi vào phần viết code.

Cập nhật bản ghi trong bảng cơ sở dữ liệu Android SQLite

Đoạn code sau đây cho thấy cách cập nhật một bản ghi duy nhất.

public int update(long _id, String name, String desc) { ContentValues contentValues = new ContentValues(); contentValues.put(DatabaseHelper.SUBJECT, name); contentValues.put(DatabaseHelper.DESC, desc); int i = database.update(DatabaseHelper.TABLE_NAME, contentValues, DatabaseHelper._ID + " = " + _id, null); return i; }

Android SQLite – Xóa một bản ghi

Chúng ta chỉ cần truyền id của bản ghi cần xóa như sau.

public void delete(long _id) { database.delete(DatabaseHelper.TABLE_NAME, DatabaseHelper._ID + "=" + _id, null); }

Android SQLite Cursor

Một Cursor đại diện cho toàn bộ kết quả của lệnh truy vấn. Sau khi lệnh truy vấn được thực hiện, tiếp tục là lệnh gọi đến cursor.moveToFirst() . Gọi moveToFirst() thực hiện hai tác vụ:

  • Cho phép chúng ta kiểm tra xem truy vấn có trả về một tập hợp giá trị rỗng hay không (bằng cách kiểm tra giá trị trả về).
  • Di chuyển con trỏ đến kết quả đầu tiên (khi tập hợp không có giá trị rỗng).

Đoạn code sau đây được sử dụng để liệt kê tất cả các bản ghi:

public Cursor fetch() { String[] columns = new String[] { DatabaseHelper._ID, DatabaseHelper.SUBJECT, DatabaseHelper.DESC }; Cursor cursor = database.query(DatabaseHelper.TABLE_NAME, columns, null, null, null, null, null); if (cursor != null) { cursor.moveToFirst(); } return cursor; }

Một cách khác để sử dụng Cursor là đưa nó vào trong một CursorAdapter. Tương tự như cách ArrayAdapter điều chỉnh mảng, CursorAdapter điều chỉnh các object Cursor, làm cho dữ liệu của chúng có sẵn cho một AdapterView như ListView. Hãy xem một ví dụ dự án thực tế sử dụng SQLite để lưu trữ những dữ liệu quan trọng.

Cấu trúc dự án Android SQLite

Trong ứng dụng này, chúng ta muốn tạo các bản ghi lưu trữ tên Quốc gia và tiền tệ tương ứng của chúng dưới dạng ListView. Chúng ta sẽ đi vào chi tiết tất cả các tính năng đã thảo luận ở trên.

Code dự án Android SQLite

Ứng dụng bao gồm 5 lớp. Chúng ta bắt đầu với việc định nghĩa DatabaseHelper, là một lớp con của SQLiteOpenHelper như sau: DatabaseHelper.java.

package com.journaldev.sqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DatabaseHelper extends SQLiteOpenHelper {

    // Table Name
    public static final String TABLE_NAME = "COUNTRIES";

    // Table columns
    public static final String _ID = "_id";
    public static final String SUBJECT = "subject";
    public static final String DESC = "description";

    // Database Information
    static final String DB_NAME = "JOURNALDEV_COUNTRIES.DB";

    // database version
    static final int DB_VERSION = 1;

    // Creating table query
    private static final String CREATE_TABLE = "create table " + TABLE_NAME + "(" + _ID
            + " INTEGER PRIMARY KEY AUTOINCREMENT, " + SUBJECT + " TEXT NOT NULL, " + DESC + " TEXT);";

    public DatabaseHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE);
    }

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

Như đã đề cập ở trên, tôi đã ghi đè các phương thức onCreate()onUpgrade() bên cạnh hàm tạo. Chúng ta đã gán tên cho cơ sở dữ liệu và bảng lần lượt là JOURNALDEV_COUNTRIES.DBCOUNTRIES. Cột chỉ mục được tự động tăng lên mỗi khi một hàng mới được chèn vào. Tên cột cho quốc gia và tiền tệ là “subject” và “description”. Lớp DBManager là nơi DatabaseHelper được khởi tạo và các thao tác CRUD được định nghĩa. Dưới đây là đoạn code cho lớp này: DBManager.java.

package com.journaldev.sqlite;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;

public class DBManager {

    private DatabaseHelper dbHelper;

    private Context context;

    private SQLiteDatabase database;

    public DBManager(Context c) {
        context = c;
    }

    public DBManager open() throws SQLException {
        dbHelper = new DatabaseHelper(context);
        database = dbHelper.getWritableDatabase();
        return this;
    }

    public void close() {
        dbHelper.close();
    }

    public void insert(String name, String desc) {
        ContentValues contentValue = new ContentValues();
        contentValue.put(DatabaseHelper.SUBJECT, name);
        contentValue.put(DatabaseHelper.DESC, desc);
        database.insert(DatabaseHelper.TABLE_NAME, null, contentValue);
    }

    public Cursor fetch() {
        String[] columns = new String[] { DatabaseHelper._ID, DatabaseHelper.SUBJECT, DatabaseHelper.DESC };
        Cursor cursor = database.query(DatabaseHelper.TABLE_NAME, columns, null, null, null, null, null);
        if (cursor != null) {
            cursor.moveToFirst();
        }
        return cursor;
    }

    public int update(long _id, String name, String desc) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(DatabaseHelper.SUBJECT, name);
        contentValues.put(DatabaseHelper.DESC, desc);
        int i = database.update(DatabaseHelper.TABLE_NAME, contentValues, DatabaseHelper._ID + " = " + _id, null);
        return i;
    }

    public void delete(long _id) {
        database.delete(DatabaseHelper.TABLE_NAME, DatabaseHelper._ID + "=" + _id, null);
    }

}

Lớp CountryListActivity.java là activity được khởi chạy khi ứng dụng khởi động. Bố cục được định nghĩa là fragment_emp_list.xml.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="<https://schemas.android.com/apk/res/android>"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:dividerHeight="1dp"
        android:padding="10dp" >
    </ListView>

    <TextView
        android:id="@+id/empty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/empty_list_text" />

</RelativeLayout>

Một component ListView được định nghĩa để chứa các bản ghi được lưu trữ trong cơ sở dữ liệu. Ban đầu, ListView sẽ trống, do đó một TextView được sử dụng để hiển thị điều này. CountryListActivity.java.

package com.journaldev.sqlite;

import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;

public class CountryListActivity extends ActionBarActivity {

    private DBManager dbManager;

    private ListView listView;

    private SimpleCursorAdapter adapter;

    final String[] from = new String[] { DatabaseHelper._ID,
            DatabaseHelper.SUBJECT, DatabaseHelper.DESC };

    final int[] to = new int[] { R.id.id, R.id.title, R.id.desc };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.fragment_emp_list);

        dbManager = new DBManager(this);
        dbManager.open();
        Cursor cursor = dbManager.fetch();

        listView = (ListView) findViewById(R.id.list_view);
        listView.setEmptyView(findViewById(R.id.empty));

        adapter = new SimpleCursorAdapter(this, R.layout.activity_view_record, cursor, from, to, 0);
        adapter.notifyDataSetChanged();

        listView.setAdapter(adapter);

        // OnCLickListiner For List Items
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long viewId) {
                TextView idTextView = (TextView) view.findViewById(R.id.id);
                TextView titleTextView = (TextView) view.findViewById(R.id.title);
                TextView descTextView = (TextView) view.findViewById(R.id.desc);

                String id = idTextView.getText().toString();
                String title = titleTextView.getText().toString();
                String desc = descTextView.getText().toString();

                Intent modify_intent = new Intent(getApplicationContext(), ModifyCountryActivity.class);
                modify_intent.putExtra("title", title);
                modify_intent.putExtra("desc", desc);
                modify_intent.putExtra("id", id);

                startActivity(modify_intent);
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();
        if (id == R.id.add_record) {

            Intent add_mem = new Intent(this, AddCountryActivity.class);
            startActivity(add_mem);

        }
        return super.onOptionsItemSelected(item);
    }

}

Trong activity này, object DBManager được gọi để thực hiện các thao tác CRUD. Một SimpleCursorAdapter được định nghĩa để thêm các phần tử vào danh sách từ kết quả truy vấn được trả về trong một object Cursor. Khi nhấp vào một mục trong danh sách, một intent được thực hiện để mở lớp ModifyCountryActivity. Menu chứa một mục để thêm một bản ghi mới từ ActionBar. Tại đây, một intent lại được thực hiện để mở lớp AddCountryActivity. Sau đây là đoạn code menu.xml

<menu xmlns:android="<https://schemas.android.com/apk/res/android>"
    xmlns:app="<https://schemas.android.com/apk/res-auto>"
    xmlns:tools="<https://schemas.android.com/tools>"
    tools:context="com.example.sqlitesample.MainActivity" >

    <item
        android:id="@+id/add_record"
        android:icon="@android:drawable/ic_menu_add"
        android:orderInCategory="100"
        android:title="@string/add_record"
        app:showAsAction="always"/>

</menu>

Bố cục XML và mã của tệp AddCountryActivity.java được định nghĩa như sau: activity_add_record.xml.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="<https://schemas.android.com/apk/res/android>"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="20dp" >

    <EditText
        android:id="@+id/subject_edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="@string/enter_title" >

        <requestFocus />
    </EditText>

    <EditText
        android:id="@+id/description_edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="@string/enter_desc"
        android:inputType="textMultiLine"
        android:minLines="5" >
    </EditText>

    <Button
        android:id="@+id/add_record"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/add_record" />

</LinearLayout>

Đã định nghĩa hai trường EditText để nhập thông tin về quốc gia và tiền tệ, cùng với một nút để thêm các giá trị này vào cơ sở dữ liệu và hiển thị trên ListView.AddCountryActivity.java

package com.journaldev.sqlite;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class AddCountryActivity extends Activity implements OnClickListener {

    private Button addTodoBtn;
    private EditText subjectEditText;
    private EditText descEditText;

    private DBManager dbManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setTitle("Add Record");

        setContentView(R.layout.activity_add_record);

        subjectEditText = (EditText) findViewById(R.id.subject_edittext);
        descEditText = (EditText) findViewById(R.id.description_edittext);

        addTodoBtn = (Button) findViewById(R.id.add_record);

        dbManager = new DBManager(this);
        dbManager.open();
        addTodoBtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.add_record:

                final String name = subjectEditText.getText().toString();
                final String desc = descEditText.getText().toString();

                dbManager.insert(name, desc);

                Intent main = new Intent(AddCountryActivity.this, CountryListActivity.class)
                        .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

                startActivity(main);
                break;
        }
    }

}

Thao tác CRUD được thực hiện ở đây là thêm một bản ghi mới vào cơ sở dữ liệu. Bố cục XML và code của tệp ModifyCountryActivity.java được định nghĩa dưới đây: activity_modify_record.xml.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="<https://schemas.android.com/apk/res/android>"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp" >

    <EditText
        android:id="@+id/subject_edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:ems="10"
        android:hint="@string/enter_title" />

    <EditText
        android:id="@+id/description_edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="@string/enter_desc"
        android:inputType="textMultiLine"
        android:minLines="5" >
    </EditText>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:weightSum="2"
        android:gravity="center_horizontal"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btn_update"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/btn_update" />

        <Button
            android:id="@+id/btn_delete"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/btn_delete" />
    </LinearLayout>

</LinearLayout>

Phần bố cục và code của ModifyCountryActivity.java cũng tương tự như bố cục trước đó, ngoại trừ việc thêm vào các nút sửa đổi và xóa.

package com.journaldev.sqlite;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class ModifyCountryActivity extends Activity implements OnClickListener {

    private EditText titleText;
    private Button updateBtn, deleteBtn;
    private EditText descText;

    private long _id;

    private DBManager dbManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setTitle("Modify Record");

        setContentView(R.layout.activity_modify_record);

        dbManager = new DBManager(this);
        dbManager.open();

        titleText = (EditText) findViewById(R.id.subject_edittext);
        descText = (EditText) findViewById(R.id.description_edittext);

        updateBtn = (Button) findViewById(R.id.btn_update);
        deleteBtn = (Button) findViewById(R.id.btn_delete);

        Intent intent = getIntent();
        String id = intent.getStringExtra("id");
        String name = intent.getStringExtra("title");
        String desc = intent.getStringExtra("desc");

        _id = Long.parseLong(id);

        titleText.setText(name);
        descText.setText(desc);

        updateBtn.setOnClickListener(this);
        deleteBtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_update:
                String title = titleText.getText().toString();
                String desc = descText.getText().toString();

                dbManager.update(_id, title, desc);
                this.returnHome();
                break;

            case R.id.btn_delete:
                dbManager.delete(_id);
                this.returnHome();
                break;
        }
    }

    public void returnHome() {
        Intent home_intent = new Intent(getApplicationContext(), CountryListActivity.class)
                .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(home_intent);
    }
}

Các thao tác CRUD được thực hiện ở đây là cập nhật và xóa một bản ghi. Các hình ảnh dưới đây là ảnh chụp màn hình kết quả cuối cùng của dự án. Hình ảnh đầu tiên là giao diện khi ứng dụng được khởi chạy lần đầu tiên.

Hình ảnh thứ hai là kết quả khi nhấp vào tùy chọn menu từ ActionBar để thêm một bản ghi mới như minh họa bên dưới.

Hình ảnh thứ ba hiển thị kết quả khi 3 bản ghi được thêm vào.

Hình ảnh thứ tư hiển thị kết quả khi bất kỳ mục danh sách nào được nhấp để sửa đổi hoặc xóa một bản ghi.

Hình ảnh cuối cùng là kết quả khi một bản ghi bị xóa. Trong ví dụ này, chúng ta xóa bản ghi đầu tiên.

Mở tệp Cơ sở dữ liệu Android SQLite

Tệp cơ sở dữ liệu được lưu trữ trong bộ nhớ trong và có thể truy cập bằng cách sử dụng Android Device Monitor.

Để xem cơ sở dữ liệu này, chúng ta cần kéo tệp này từ trong ra ngoài màn hình chính (desktop). Thao tác thực hiện bằng cách nhấp vào tùy chọn menu ở trên cùng bên phải như hình minh họa sau.

Để mở tệp này, hãy tải về SQLiteBrowser. Các đoạn code dưới đây hiển thị schema và các bảng trong trình duyệt.

Để xem bảng, hãy chuyển đến tab “Browse Data” ở trên cùng. Bạn sẽ thấy giao diện như sau:

Và đến đây là kết thúc phần hướng dẫn về Android SQLite. Hy vọng hướng dẫn này đã cung cấp cho bạn cái nhìn toàn diện về cách làm việc với SQLite trong các ứng dụng Android. Giờ đây, bạn đã có kiến thức cơ bản để bắt đầu xây dựng các ứng dụng Android “xịn sò” với khả năng lưu trữ dữ liệu hiệu quả.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.