Envíe 1 archivo de configuración según el estado actual y la construcción del el. Cliente con notas notariales en relación con el servicio de newsapi.org. Definición visual de la montaña desde el punto de vista de la aplicación visual y vista ViewModel que conecta con la fuente de datos.
Nuestra aplicación solo requiere 2 diseños:
- activity_news: Vea la vista principal de nuestra aplicación. Para generar este archivo, refactorice -> Cambie el nombre del archivo activity_main.xml
- item_view: Vea la vista de cada una de nuestras noticias.
activity_news.xml
En este caso, el padre es un FrameLayout, pero además de los hijos que ocupan todo el espacio en la pantalla, puede volver a cargarlo con otro diseño como LinearLayour o ConstraintLayout.
Agregaremos un SwipeRefresh Preview Layout Nuestra Colouremos Nuestro RecyclerView.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".NewsActivity">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/swipeRefreshLayout">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerNews"
android:layout_width="match_parent"
android:layout_height="match_parent"></androidx.recyclerview.widget.RecyclerView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</FrameLayout>
item_view.xml
Es una vista real, es un ConstraintLayout con 3 TextViews para describir el título de la noticia, la descripción o el resumen y la fecha de publicación. Estos 3 datos se agregan a la vista mediana de DataBinding con una instancia de nuestra clase de datos: artículo.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"><data class="ArticleBinding">
<variable
name="article"
type="com.hms.demo.hquicnews.Article" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="@color/gray"
android:clickable="true"
android:elevation="5dp"
android:padding="5dp">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@{article.title}"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@{article.description}"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title" />
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@{article.time}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/content" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Tan pronto como sea posible, el texto Text de cada TextView se asocia con una propiedad de nuestra instancia de Artículo definida dentro de la etiqueta .
Definimos una clase de noticias NewsViewModel que se extiende desde ViewModel. Es necesario comunicar nuestra actividad con la fuente de datos, además de la memoria de nuestra lista de notas, que no se ve afectada por la rotación de la pantalla.
class NewsViewModel : ViewModel(), NewsClient.NewsClientListener {
private val API_KEY="YOUR_API_KEY" //get your API key here: https://newsapi.org/register
private val URL = "https://newsapi.org/v2/top-headlines?apiKey=$API_KEY"
private val METHOD = "GET"
var newsClient:NewsClient?=nullprivate val _news=MutableLiveData<ArrayList<Article>>().apply{
value= ArrayList()
}
val news: LiveData<ArrayList<Article>> = _news
}
Nota: Para demostrar efectos efectivos, la clave API de newsapi.org de la clase NewsViewModel, sin embargo, para conservar sus claves y guardarla, es muy recomendable esta guía.
Comunicarse con la actividad
Nos gustaría notificar a la Actividad cuando se complete la descarga de noticias, para cambiar el estado de SwipeRefreshLayout. Las definiciones incluyen una interfaz para indicar la actividad en la que la descarga está completa o el usuario hace clic en las noticias.
interface NewsViewModelListener{
fun onNewsDownloadComplete()
fun onItemClick(article: Article)
}
Descargando la noticia
Nuestro ViewModel se enfoca en mensajes de instancia de NewsClient para crear mensajes dentro de la noticia según el país que se configure en el sistema.
public fun getNews(context: Context,country:String=Locale.getDefault().country) {
if(newsClient==null){
newsClient=NewsClient(context)
}
val url= "$URL&country=$country"
newsClient?.apply {
[email protected]
getNews(url,METHOD)
}
}
Escuchando la respuesta
Registraremos los métodos de la interfaz NewsClientListener para buscar el resultado de la petición. Si la noticia se actualiza satisfactoriamente, MutableLiveData se actualizará para contener una lista de noticias
override fun onSuccess(news: ArrayList<Article>) {
_news.postValue(news)
listener?.onNewsDownloadComplete()
}override fun onFailure(error: String) {
listener?.onNewsDownloadComplete()
}
Gestionar la rotación de la pantalla
Si el usuario está disponible para una caminata de Retrato o Paisaje, se recomendará el ciclo de vida de nuestra actividad. Si el ViewModel indica que la noticia es enviada automáticamente a la Actividad de Initiar Nuestro, también será una petición para leer la pantalla, y mostrará la noticia. Es porque necesitamos crear un método que imponga la descarga y lea la lista de noticias.
public fun loadNews(context: Context){
news.value?.apply {
if(isEmpty()) getNews(context)
else listener?.onNewsDownloadComplete()
}
}
Este formulario cargará loadingNews de nuestro video de actividad y getNews solo cuando use SwipeRefreshLayout para reflejar las noticias.
Escuchando las noticias
Nuestro ViewModel se prepara para escuchar los clicks que da el usuario sobre cualquier hoja de noticias.
public fun onItemClick(article:Article){
listener?.onItemClick(article)
}
Cambios reservados al archivo item_view.xml para notificar los eventos onClick al ViewModel. Primero necesitamos agregar una variable en el elemento
<data class="ArticleBinding"><variable
name="article"
type="com.hms.demo.hquicnews.Article" />
<variable
name="mainVM"
type="com.hms.demo.hquicnews.NewsViewModel" />
</data>
Ahora es posible acordar el evento onClick a nuestro ConstraintLayout para informar al ViewModel cuando vea que el usuario hace clic en un mensaje.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="@color/gray"
android:clickable="true"
android:elevation="5dp" android:onClick="@{()->mainVM.onItemClick(article)}" android:padding="5dp">
Eso es todo por ahora. En la Parte 3 crearemos nuestro adaptador RecyclerView y acordaremos la funcionalidad de la Actividad para completar nuestra aplicación.