Upload an image from a URL in a Recycler View

1

I'm doing an exercise where I connect my application with an external database, I can retrieve text stored in a MySQL database, I have a field called a photo, it's a "varchar" and there I store a URL on it. 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 I get 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 that error, so I've read it is an error of Asynchronous tasks, I just do not know how to load the images with asynchronous tasks, I'm 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());
    }
}
    
asked by Enrique Espinosa 26.11.2018 в 19:15
source

1 answer

1

Your error is because you are requesting a network operation in the main% Thread , you have to open another Thread of execution. To solve this error use AsyncTask .

private class CargarImagenesTask extends AsyncTask<Void, Void, Void> {

   @Override
   protected Void doInBackground(Void... params) {
        // Aquí tu codigo para llamar a la URL
   }

    @Override
    protected void onPostExecute(Void param) {
        // Envías los cambios al adaptador del recyclerview
        mAdapter.notifyDataSetChanged();
    }
}

However you can use Glide as an option and you avoid using AsyncTask like this ...

First you add the Glide reference to your project.

compile 'com.github.bumptech.glide:glide:4.2.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.2.0'

In the viewHolder you do this

@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());

    // Cambias esto para ubicar la imagen en tu recyclerview
    RequestOptions requestOptions = new RequestOptions();
    requestOptions = requestOptions.transforms(new CenterCrop(), new RoundedCorners(16));

    Glide.with(context)
        .load(listaUsuario.get(position).getFoto())
        .apply(requestOptions)
        .into(usuariosHolder.fotoRecuperado);
    }

I hope you find it useful, if you need me to expand the example, you let me know.

    
answered by 26.11.2018 / 20:40
source