Omar
Omar

Reputation: 61

How to update RecyclerView , so each item appears every N seconds?

He

I would like to know, if it's posible loading Items in RecyclerView dynamically.

I want to make a list like this application Lifeline example aplication

I tried using

    new android.os.Handler().postDelayed(
new Runnable() {
    public void run() {
        Log.i("tag", "This'll run 300 milliseconds later");
    }
},300); 

but it does not work for me because wait that long, and then displays all at once

this is my code

public class TextoAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{

private static final int TYPE_BUTTON = 0;
private static final int TYPE_TEXT = 1;

private Context context;
private int lastPosition = -1;

@Override
public int getItemViewType(int position) {
    // Just as an example, return 0 or 2 depending on position

    int viewType;
    if ( position % 2 * 2 == 0 )
    {
        viewType = TYPE_TEXT;
    }else
    {
        viewType = TYPE_BUTTON;
    }
    return TYPE_TEXT;
}

public static class TextoViewHolder extends RecyclerView.ViewHolder {
    CardView cv;
    TextView texto;
    TextoViewHolder(View itemView) {
        super(itemView);
        cv = (CardView)itemView.findViewById(R.id.cv_texto);
        texto = (TextView)itemView.findViewById(R.id.texto);
    }
}

public static class ButtonViewHolder extends RecyclerView.ViewHolder {
    CardView cv_btn;
    Button izq, der;
    ButtonViewHolder(View itemView) {
        super(itemView);
        cv_btn = (CardView)itemView.findViewById(R.id.cv_botones);
        izq = (Button)itemView.findViewById(R.id.btn_izquierdo);
        der = (Button)itemView.findViewById(R.id.btn_derecho);
    }
}

List<Texto> textos;
LinearLayoutManager llm;
RecyclerView rv;


public TextoAdapter(List<Texto> textos, LinearLayoutManager llm,RecyclerView rv,Context context){
    this.textos = textos;
    this.llm = llm;
    this.rv = rv;
    this.context = context;
}

public void addItemsToList (Texto texto){
    textos.add(texto);
    this.notifyDataSetChanged();
    rv.smoothScrollToPosition(getItemCount());

}


@Override
public int getItemCount() {
    return textos.size();
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {

    LayoutInflater mInflater = LayoutInflater.from ( viewGroup.getContext () );
    switch ( viewType ) {

        case TYPE_TEXT:
            View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.texto_card, viewGroup, false);
            TextoViewHolder pvh = new TextoViewHolder(v);
            return pvh;
        case TYPE_BUTTON:
            ViewGroup v2 = ( ViewGroup ) mInflater.inflate (R.layout.botones_card, viewGroup, false);
            ButtonViewHolder vhGroup = new ButtonViewHolder(v2);
            return vhGroup;
        default:
            View v3 = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.texto_card, viewGroup, false);
            TextoViewHolder pvh3 = new TextoViewHolder(v3);
            return pvh3;
    }


}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int i) {

    switch ( holder.getItemViewType () ) {

        case TYPE_TEXT:
            TextoViewHolder textoViewHolder = ( TextoViewHolder ) holder;

            textoViewHolder.texto.setText(textos.get(i).texto);
            setAnimation(textoViewHolder.cv, i);
            textoViewHolder.cv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    addItemsToList(new Texto("otroooooo"));

                }
            });
            break;

        case TYPE_BUTTON:

            ButtonViewHolder buttonViewHolder = ( ButtonViewHolder ) holder;
            setAnimation(buttonViewHolder.cv_btn, i);
            buttonViewHolder.izq.setText("SI");
            buttonViewHolder.der.setText("NO");

            break;

    }
}

/**
 * Here is the key method to apply the animation
 */
private void setAnimation(View viewToAnimate, int position)
{
    // If the bound view wasn't previously displayed on screen, it's animated
    if (position > lastPosition)
    {
        //Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
        Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.fade_in);
        animation.setDuration(1000);
        viewToAnimate.startAnimation(animation);
        lastPosition = position;
    }
}


@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
}

Main

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    RecyclerView rv = (RecyclerView)findViewById(R.id.rv);
    LinearLayoutManager llm = new LinearLayoutManager(this);
    rv.setLayoutManager(llm);

    List<Texto> textos;

    textos = new ArrayList<>();

    textos.add(new Texto("Hola y bienvenido al juego"));
    TextoAdapter adapterTextos = new TextoAdapter(textos,llm,rv,this );
    rv.setAdapter(adapterTextos);

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

Thanks

Upvotes: 1

Views: 1985

Answers (1)

Jędrzej Kołtunowicz
Jędrzej Kołtunowicz

Reputation: 181

I think one of the solutions is to make two ArrayLists and copy texts from one to another and keep notifying the adapter - something like this:

Make two arrays:

ArrayList<String> textsQueue;        // put all the texts here
ArrayList<String> textos;           // pass it to the adapter

Use ScheduledExecutorService or other timer. I'd do somethinkg like this:

ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
int currentTextNo = 0; 
Runnable nextText = new Runnable {
    @Override
    public void run() {
        textos.add(textsQueue.get(currentTextNo));
        currentTextNo++;
        adapter.notifyDataSetChanged();

        if (currentTextNo == textsQueue.size()) {
           ses.shutdownNow();
        }
    }
};
// the parameters are: runnable, initial delay, period, time unit 
ses.scheduleAtFixedRate(nextText, 0, 300, TimeUnit.MILLISECONDS);

I don't know if this is an optimal solution, and I didn't validate the code, but I think it could work. I think you can even make the texts appear after random time. To do this, you could - and this is only my speculation - instead of using scheduleAtFixedRate use scheduleWithFixedDelay and put some delay mechanism at the end of the run() method. Anyway - good luck!

Upvotes: 1

Related Questions