sql >> Base de Datos >  >> RDS >> SQLite

¿Cómo obtener el primer elemento o (cualquiera) de una lista LiveData en la arquitectura MVVM de Android?

cómo obtener el primer elemento o (cualquiera) de una lista LiveData en la arquitectura AndroidMVVM

Si desea obtener un elemento en particular de una lista de LiveData, debe limitar su consulta con un desplazamiento.

De forma predeterminada, limitar una consulta no considera un desplazamiento; por lo que el valor de compensación predeterminado es 0.

Por ejemplo, en tu Dao :

Las siguientes consultas de los ejemplos 1 y 2 son equivalentes, porque el valor de compensación predeterminado es 0.

Ejemplo

@Query("SELECT * FROM students LIMIT  :limit")
LiveData<List<Student>> getStudents(int limit);

// Query
getStudents(1); // returns the first row of the list

Ejemplo 2

@Query("SELECT * FROM students LIMIT  :limit OFFSET :offset")
LiveData<List<Student>> getStudents(int limit, int offset);

// Query
getStudents(1, 0); // returns the first row of the list

Nota: Aquí asumo que su clase modelo es Student

Esto es sobre la primera fila; pero para devolver el número de fila x entonces necesita manipular el desplazamiento para que sea:x-1 , ya que el desplazamiento es un valor basado en 0

Ejemplo 3 (Misma consulta de Dao que el Ejemplo 2)

getStudents(1, 1); // returns the second row
getStudents(1, 4); // returns the fifth row

Si desea devolver más de una fila, debe manipular el LIMIT valor, para devolver x filas de los resultados, luego limite la consulta con x .

getStudents(2, 1); // returns the second and third rows
getStudents(3, 4); // returns the fifth, sixth, and seventh rows

Espero que esto responda a tu pregunta

Editar según comentarios

Ya tengo una lista devuelta por otra consulta @Query("SELECT * FROM students) LiveData<List<Student>> getStudents(); Entonces el valor devuelto es una lista. Quiero obtener el primer elemento de la lista. Esta respuesta realmente devuelve el primer elemento, pero necesito pasar todos los pasos (para definir este método en el ViewModel class y obsérvelo en MainActivity para obtener la lista o cualquier elemento de la lista). Lo que necesito es escribir el primer valor en la lista mientras entretengo la función en la clase de repositorio. –

Ahora está utilizando la siguiente consulta

@Query("SELECT * FROM students")
LiveData<List<Student>> getStudents();

Y quieres:

  1. Obtenga el primero o cualquier elemento de la lista. y hacerlo de acuerdo con lo mencionado anteriormente
  2. Pase todos los pasos (para definir este método en el ViewModel class y obsérvelo en MainActivity para obtener la lista o cualquier elemento de la lista).

Así que para hacer eso:

En Dao: :Cambie su consulta a

@Query("SELECT * FROM students LIMIT  :limit OFFSET :offset")
LiveData<List<Student>> getAllStudents(int limit, int offset);

En repositorio:

public class StudentRepository {

    ...

    public LiveData<List<Student>> getAllStudents(final int limit, final int offset) {
        return mDAO.getAllStudents(limit, offset);
    }
}

En ViewModel:

public LiveData<List<Student>> getAllStudents(final int limit, final int offset) {
    return mRepository.getAllStudents(limit, offset);
}

En actividad:

private void getAllStudents(int limit, int offset) {
    mViewModel.getAllStudents(limit, offset).observe(this, new Observer<List<Student>>() {
        @Override
        public void onChanged(List<Student> students) {
            if (students != null) {
                // Here you can set RecyclerView list with `students` or do whatever you want

            }
        }
    });
}

Y para probar eso:

getAllStudents(1, 0); // return first row from the table.
getAllStudents(2, 0); // return first 2 rows from the table.
getAllStudents(2, 1); // return 2nd and 3rd rows from the table.
getAllStudents(-1, 5); // remove first 5 rows from the table.

Y para devolver el primer elemento en la lista mAllStudents para escribir el nombre del primer estudiante en Log.d

Entonces, en tu actividad

mViewModel.getAllStudents(1, 0).observe(this, new Observer<List<Student>>() {
    @Override
    public void onChanged(List<Student> students) {
        if (students != null) {
            Student student = students.get(0);
            Log.d("First_Name", student.getName());
        }
    }
});

Editar, ¿es posible devolver cualquier elemento de la lista sin seguir todos los pasos, como escribir una función en ViewModel y observar eso en MainActivity? Mi duda es no seguir todos los pasos.

Sí, es posible, pero el modelo anterior es el modelo recomendado por Google. Puede devolver una List<Student> de Dao consulta en lugar de LiveData<List<Student>> , pero las malas noticias son:

  1. Tienes que manejar eso en un hilo de fondo separado; porque los LiveData hazlo gratis.
  2. Perderás el valor de LiveData; por lo tanto, debe actualizar manualmente la lista para verificar cualquier actualización, ya que no podrá usar el patrón de observador.

Entonces, puede omitir el uso de ViewModel y Repository y haz todas las cosas de la actividad de la siguiente manera:

private Executor mExecutor = Executors.newSingleThreadExecutor();

public void getAllStudents(final int limit, final int offset) {

    final StudentDAO mDAO = StudentDatabase.getInstance(getApplicationContext()).getStudentDAO();

    mExecutor.execute(new Runnable() {
        @Override
        public void run() {
            List<Student> students = mDAO.getAllStudents(limit, offset);
            Student student = students.get(0);
            Log.d("First_Name", student.getName());
        }
    });
}

// Usage: getAllStudents(1, 0);

Y la consulta para el Dao:

@Query("SELECT * FROM students LIMIT  :limit OFFSET :offset")
List<Student> getAllStudents(int limit, int offset);