*Hello, one question, how can I load a ArrayList
with internet data? What I want to achieve is to enter a text in a EditText
and that when pressing Button
a recyclerview is loaded with all the data of that search.
I have created the following class :
public class ParseItem {
private String imgUrl;
private String title;
private String detailUrl;
public ParseItem() {
}
public ParseItem(String imgUrl, String title, String detailUrl) {
this.imgUrl = imgUrl;
this.title = title;
this.detailUrl = detailUrl;
}
public String getImgUrl() {
return imgUrl;
}
public void setImgUrl(String imgUrl) {
this.imgUrl = imgUrl;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDetailUrl() {
return detailUrl;
}
public void setDetailUrl(String detailUrl) {
this.detailUrl = detailUrl;
}
}
I pass it to the adapter :
public class ParseAdapter extends RecyclerView.Adapter<ParseAdapter.ViewHolder> {
private ArrayList<ParseItem> parseItems;
private Context context;
public ParseAdapter(ArrayList<ParseItem> parseItems, Context context) {
this.parseItems = parseItems;
this.context = context;
}
@NonNull
@Override
public ParseAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.parse_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ParseAdapter.ViewHolder holder, int position) {
ParseItem parseItem = parseItems.get(position);
holder.textView.setText(parseItem.getTitle());
Picasso.get().load(parseItem.getImgUrl()).into(holder.imageView);
}
@Override
public int getItemCount() {
return parseItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
ImageView imageView;
TextView textView;
public ViewHolder(@NonNull View view) {
super(view);
imageView = view.findViewById(R.id.imageView);
textView = view.findViewById(R.id.textView);
view.setOnClickListener(this);
}
}
public void setFilter(ArrayList<ParseItem> newList) {
parseItems = new ArrayList<>();
parseItems.addAll(newList);
notifyDataSetChanged();
}
}
And this is what I do in the activity :
public class MainActivity extends AppCompatActivity {
Button buscar;
EditText textoBusqueda;
private RecyclerView recyclerView;
private ParseAdapter adapter;
private ArrayList<ParseItem> parseItems = new ArrayList<>();
private ProgressBar progressBar;
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
progressBar = findViewById(R.id.progressBar);
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new ParseAdapter(parseItems, this);
recyclerView.setAdapter(adapter);
textoBusqueda = (EditText)findViewById(R.id.etBuscar);
String texto = textoBusqueda.getText().toString();
buscar = (Button)findViewById(R.id.btnBusqueda);
buscar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(TextUtils.isEmpty(textoBusqueda.getText())){
Toast.makeText(MainActivity.this, "Debe ingresar el nombre del libro.", Toast.LENGTH_LONG).show();
textoBusqueda.setFocusable(true);
}else{
Content content = new Content();
content.execute();
}
}
});
}
private class Content extends AsyncTask<Void,Void,Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
progressBar.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.fade_in));
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
progressBar.setVisibility(View.GONE);
progressBar.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.fade_out));
adapter.notifyDataSetChanged();
}
@Override
protected Void doInBackground(Void... voids) {
String url = "https://trantor.is/search/?q="+ textoBusqueda.getText().toString();
try {
Document doc = Jsoup.connect(url).get();
Elements data = doc.select("div.span1");
int size = data.size();
Log.d("doc", "doc: "+doc);
Log.d("data", "data: "+data);
Log.d("size", ""+size);
for (int i = 0; i < size; i++) {
String imgUrl = data.select("div.span1")
.select("img")
.eq(i)
.attr("src");
String title = data.select("div.span7")
.select("span")
.eq(i)
.text();
String detailUrl = data.select("div.span7")
.select("a")
.eq(i)
.attr("href");
parseItems.add(new ParseItem(imgUrl, title, detailUrl));
Log.d("items", "img: " + imgUrl + " . title: " + title);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
I attach the one layout
of the activity
:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:background="@color/negro">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/linearBuscar"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:layout_height="70dp"
android:orientation="horizontal">
<EditText
android:textColor="@color/blanco"
android:hint="Buscar..."
android:textColorHint="@color/blanco"
android:layout_marginTop="10dp"
android:layout_width="180dp"
android:layout_height="50dp"
android:id="@+id/etBuscar"/>
<Button
android:layout_marginTop="10dp"
android:layout_width="50dp"
android:layout_height="50dp"
android:textColor="@color/blanco"
android:id="@+id/btnBusqueda"
android:background="@drawable/ic_search"/>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="50dp"
android:layout_height="50dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:indeterminate="true"
android:visibility="gone"/>
</LinearLayout>
</RelativeLayout>
And the one layout
from adaptador
:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="165dp"
style="@style/CardView.Light"
android:layout_margin="8dp"
tools:ignore="MissingConstraints">
<ImageView
android:id="@+id/imageView"
android:layout_width="120dp"
android:layout_height="120dp"
android:scaleType="centerCrop"
android:src="#88888888"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_gravity="bottom"
android:src="@drawable/gradient"/>
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Title"
style="@style/TextAppearance.AppCompat.Medium"
android:layout_gravity="bottom"
android:layout_margin="12dp"
android:textColor="#fff"/>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
But, nothing loads for me and the logcat shows no errors, any suggestions?
When reviewing your code I can see two problems that prevent seeing your data, the incorrect use of
AsyncTask
and the parsing using JSoup .Firstly, regarding data retrieval, remember that
doInBackground()
you must use the method to perform the data retrieval process but it is important to specify the return value (don't use null), you would get the return value inonPostExecute()
and this is where you would update the values of your Adapter.To update I suggest you add the following method in the Adapter that would be called in
onPostExecute()
and this would be the change in your AsyncTask, getting the data in
doInBackground()
and updating usingonPostExecute()
:Now, a problem for which you would not visualize the data is the parsing of the same within the web page https://trantor.is/search/?q=el+little-prince , the correct way using JSoup would be done as follows :
Es importante tomar en cuenta que si usas un
ConstraintLayout
debes agregar restricciones a las vistas de otra forma tendràs problemas al desplegar los elementos en la vista. Es muy importante revisar:Cómo crear una IU responsiva con ConstraintLayout
Debes cuidar los colores, por ejemplo si tienes un fondo blanco y agregas un texto color blanco, este no se mostrarà en tu app.
Este es un layout
parse_item.xml
modificado el cual se mostrarìa correctamente.Para que al llenar los datos en tu Adapter se muestren de esta forma:
Revisa el ejemplo:
https://github.com/Jorgesys/Android-JSOAP