结丹期

8. 什么是 Android 的 ViewModel?它在应用架构中起到什么作用?

ViewModelAndroid Jetpack 架构组件的一部分,负责保存和管理与 UI 相关的数据,使数据在屏幕旋转或 Activity/Fragment 重建时得以保留。

ViewModel 的作用

  • 生命周期感知ViewModel 可以存活于 ActivityFragment 的整个生命周期,即使界面重建(如屏幕旋转)也不会丢失数据。

  • 分离逻辑与界面:通过 ViewModel,数据和业务逻辑可以与 UI 完全分离,便于代码的维护和测试。

示例

public class MyViewModel extends ViewModel {
    private MutableLiveData<Integer> counter;

    public LiveData<Integer> getCounter() {
        if (counter == null) {
            counter = new MutableLiveData<>();
            counter.setValue(0);
        }
        return counter;
    }

    public void incrementCounter() {
        counter.setValue(counter.getValue() + 1);
    }
}

ViewModel 保存了 counter 变量,即使 Activity 重建,数据也不会丢失。


9. 如何在 Android 中实现数据持久化?常见的存储方式有哪些?

Android 提供了多种数据持久化方式,开发者可以根据数据的大小、类型和应用场景选择合适的存储方法。

常见的存储方式

  • SharedPreferences:用于存储简单的键值对数据,适合保存用户设置等小型数据。

  • 文件存储:将数据保存到设备内部或外部存储,适合存储文件、图片等。

  • SQLite 数据库:用于存储结构化数据,适合处理复杂数据关系。

  • Room 数据库SQLite 的高级抽象,简化了数据库操作,提供了类型安全和易于使用的接口。

  • Content Provider:用于在不同应用之间共享数据。

每种存储方式都有不同的使用场景,应根据具体需求选择合适的方案。


10. 什么是 SharedPreferences?如何在应用中存储和读取简单的键值对数据?

SharedPreferencesAndroid 提供的用于存储简单键值对数据的轻量级存储机制,适合保存应用的设置、用户偏好等。

存储数据的示例

SharedPreferences sharedPref = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("username", "JohnDoe");
editor.putInt("age", 25);
editor.apply();  // 提交更改

读取数据的示例

SharedPreferences sharedPref = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
String username = sharedPref.getString("username", "defaultName");
int age = sharedPref.getInt("age", 0);

通过 putString()putInt() 等方法将数据存入 SharedPreferences,并通过 getString()getInt() 等方法读取数据。


11. 如何在 Android 中使用 SQLite?如何通过 Room 库简化数据库操作?

SQLiteAndroid 内置的轻量级关系型数据库,用于存储结构化数据。通过 SQLiteOpenHelper 类,开发者可以创建和管理数据库。

SQLite 示例

public class MyDatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "MyDatabase.db";
    private static final int DATABASE_VERSION = 1;

    public MyDatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)");
    }

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

RoomJetpack 提供的数据库库,它通过注解简化了 SQLite 的使用,并提供了类型安全的接口。

定义 EntityDAO 的示例

@Entity
public class User {
    @PrimaryKey
    public int id;

    public String name;
    public int age;
}

@Dao
public interface UserDao {
    @Insert
    void insertUser(User user);

    @Query("SELECT * FROM User")
    List<User> getAllUsers();
}

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
}

通过 Room 注解简化了数据库表的创建、插入和查询操作,不再需要手动编写 SQL 语句。


12. 如何在 Android 中使用 Content Provider 共享数据?

Content ProviderAndroid 中的组件之一,允许不同应用之间共享数据。

开发者可以通过定义自己的 Content Provider 来公开应用的数据,或者使用系统提供的 Content Provider(如联系人、媒体等)。

Content Provider 的工作流程

  • 定义 Content Provider,实现数据的插入、查询、更新和删除(CRUD 操作)。

  • 其他应用通过 ContentResolver 来访问 Content Provider 提供的数据。

查询系统联系人数据的示例

Cursor cursor = getContentResolver().query(
    ContactsContract.Contacts.CONTENT_URI, 
    null, null, null, null
);

if (cursor.moveToFirst()) {
    do {
        String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
        // 处理联系人数据
    } while (cursor.moveToNext());
}
cursor.close();

通过 ContentResolver 查询系统的联系人数据,遍历 Cursor 获取每个联系人的名称。


13. 什么是 Service?Service 的生命周期是怎样的?

ServiceAndroid 中的一种组件,专门用于执行后台任务,即使应用界面不可见,Service 仍然可以在后台运行。

Service 的生命周期方法

  • onCreate()Service 创建时调用,进行初始化工作。

  • onStartCommand():每次启动 Service 时调用,用于处理实际的业务逻辑。

  • onDestroy()Service 被销毁时调用,进行资源清理。

Service 的两种类型

  • 前台服务(Foreground Service):在通知栏显示持续运行的通知,适用于长时间运行的任务。

  • 后台服务(Background Service):没有用户界面的任务,但可能会被系统终止。

示例

public class MyService extends Service {
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 执行后台任务
        return START_STICKY;  // 服务在被终止后自动重启
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

14. 如何在 Android 中实现多线程?如何使用 AsyncTask 和 Handler?

Android 的主线程负责处理 UI 操作,因此耗时操作(如网络请求、数据库访问)必须在工作线程中执行,以避免阻塞 UI 线程。

AsyncTaskAndroid 提供的简化多线程开发的工具类,专门用于处理后台任务,并在任务完成后更新 UI

AsyncTask 示例

private class DownloadTask extends AsyncTask<Void, Void, String> {
    @Override
    protected String doInBackground(Void... voids) {
        // 在后台执行耗时操作
        return "Download Complete";
    }

    @Override
    protected void onPostExecute(String result) {
        // 更新 `UI`
        textView.setText(result);
    }
}

new DownloadTask().execute

();

Handler 用于在工作线程和主线程之间传递消息,适合更复杂的多线程通信场景。

Handler 示例

Handler handler = new Handler(Looper.getMainLooper());
new Thread(new Runnable() {
    @Override
    public void run() {
        // 在后台执行任务
        handler.post(new Runnable() {
            @Override
            public void run() {
                // 更新 `UI`
                textView.setText("Task Complete");
            }
        });
    }
}).start();

Handler 将任务切换到主线程,在工作线程完成任务后更新 UI

results matching ""

    No results matching ""