I am doing an exercise where I connect my application with an external database, I can now retrieve text stored in a MySQL database, I have a field called photo, it is a "varchar" and there I store a URL the problem is that when I load the image in ImageView I use the following code:
try {
URL url = new URL(listaUsuario.get(position).getFoto().toString());
Bitmap image =
BitmapFactory.decodeStream(url.openConnection().getInputStream());
usuariosHolder.fotoUsuario.setImageBitmap(image);
} catch (MalformedURLException e) {
Log.i("Rashomu","Error: "+e);
e.printStackTrace();
} catch (IOException e) {
Log.i("Raiton","Error: "+e);
e.printStackTrace();
}
The problem is that it gives me the following error:
6026-6026/com.example.enriq.myapplication E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.enriq.myapplication, PID: 6026 android.os.NetworkOnMainThreadException
My application stops with this error, from what I have read it is an Asynchronous task error, I just don't know how to load the images with asynchronous tasks, I am doing everything from a recycler view with card views.
This is the complete code of my adapter:
public class UsuariosAdapter extends RecyclerView.Adapter<UsuariosAdapter.UsuariosHolder> {
List<Usuario> listaUsuario;
public UsuariosAdapter(List<Usuario> listaUsuario){
this.listaUsuario = listaUsuario;
}
@Override
public UsuariosAdapter.UsuariosHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_usuarios,parent,false);
RecyclerView.LayoutParams layoutParams = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
view.setLayoutParams(layoutParams);
return new UsuariosHolder(view);
}
@Override
public void onBindViewHolder( UsuariosAdapter.UsuariosHolder usuariosHolder, int position) {
usuariosHolder.nombreRecuperado.setText(listaUsuario.get(position).getNombre());
usuariosHolder.apellidoRecuperado.setText(listaUsuario.get(position).getApellido());
usuariosHolder.direccionRecuperado.setText(listaUsuario.get(position).getDireccion());
usuariosHolder.fotoRecuperado.setText(listaUsuario.get(position).getFoto());
try {
URL url = new URL(listaUsuario.get(position).getFoto().toString());
Bitmap image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
usuariosHolder.fotoUsuario.setImageBitmap(image);
} catch (MalformedURLException e) {
Log.i("Rashomu","Error: "+e);
e.printStackTrace();
} catch (IOException e) {
Log.i("Raiton","Error: "+e);
e.printStackTrace();
}
}
@Override
public int getItemCount() {
return listaUsuario.size();
}
public class UsuariosHolder extends RecyclerView.ViewHolder{
TextView nombreRecuperado, apellidoRecuperado, direccionRecuperado, fotoRecuperado;
ImageView fotoUsuario;
public UsuariosHolder(View itemView){
super(itemView);
nombreRecuperado = (TextView)itemView.findViewById(R.id.tituloUsuario);
apellidoRecuperado = (TextView)itemView.findViewById(R.id.apellidoUsuario);
fotoRecuperado = (TextView)itemView.findViewById(R.id.imagenUsuario);
direccionRecuperado = (TextView)itemView.findViewById(R.id.direccionUsuario);
fotoUsuario = (ImageView)itemView.findViewById(R.id.fotoUsuario);
}
}
}
This is my User class where I have all the get and set:
package com.example.enriq.myapplication.Entidades;
public class Usuario {
private String nombre;
private String apellido;
private String direccion;
private String foto;
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getApellido() {
return apellido;
}
public void setApellido(String apellido) {
this.apellido = apellido;
}
public String getDireccion() {
return direccion;
}
public void setDireccion(String direccion) {
this.direccion = direccion;
}
public String getFoto() {
return foto;
}
public void setFoto(String foto) {
this.foto = foto;
}
}
And finally this is my main class where I retrieve the information from my database with JSON:
public class ConsultarLista extends AppCompatActivity implements Response.Listener<JSONObject>, Response.ErrorListener {
RecyclerView recyclerView;
ArrayList<Usuario> listaUsuario;
RequestQueue request;
JsonObjectRequest jsonObjectRequest;
public ConsultarLista() {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_consultar_lista);
listaUsuario = new ArrayList<>();
recyclerView = (RecyclerView)findViewById(R.id.recyclerviewU);
recyclerView.setLayoutManager(new LinearLayoutManager(this.getApplicationContext()));
recyclerView.setHasFixedSize(true);
request = Volley.newRequestQueue(getApplicationContext());
cargarWebService();
}
private void cargarWebService() {
String url = "http://192.168.1.81:80/webservice/consultarLista.php";
jsonObjectRequest = new JsonObjectRequest(Request.Method.GET,url,null,this,this);
request.add(jsonObjectRequest);
}
@Override
public void onResponse(JSONObject response) {
Usuario usuario = null;
JSONArray json = response.optJSONArray("usuario");
try{
for (int i=0; i<json.length(); i++){
usuario = new Usuario();
JSONObject jsonObject = null;
jsonObject = json.getJSONObject(i);
usuario.setNombre(jsonObject.optString("nombre"));
usuario.setApellido(jsonObject.optString("apellido"));
usuario.setDireccion(jsonObject.optString("direccion"));
usuario.setFoto(jsonObject.optString("foto"));
listaUsuario.add(usuario);
}
UsuariosAdapter adapter = new UsuariosAdapter(listaUsuario);
recyclerView.setAdapter(adapter);
}catch (JSONException e){
e.printStackTrace();
}
}
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(),"No se pudo consultar los registros: "+error.toString(), Toast.LENGTH_LONG).show();
Log.i("Error","No se pudo consultar el registro: "+error.toString());
}
}
Your error is because you are requesting a network operation on the
Thread
main, it has to open another oneThread
of execution. To solve this error useAsyncTask
.However you can use Glide as an option and avoid using
AsyncTask
it like that...First you add the Glide reference to your project.
in the
viewHolder
do thisI hope it will be useful to you, if you need me to extend the example, let me know.