Wie behandelt man mehrere Countdown-Timer in ListView?

Ich habe eine Listenansicht (mit einem benutzerdefinierten Listenadapter), ich muss in jeder Zeile einen Countdown anzeigen.

Zum Beispiel, wenn meine Liste 4 Elemente enthält, werde ich 4 Zeilen haben. An diesem Punkt muss ich 4 verschiedene Countdowns (einen für jede Zeile) behandeln, weil die Zeit anders ist.

Bildbeschreibung hier eingeben

Bisher behandele ich den folgenden Weg: Im Custom List Adapter, innerhalb der getView () Methode, erstelle ich einen neuen CountDownTimer und zeige die verbleibende Zeit in TextView an.

Aber das Problem ist, dass es die Aktivität sehr verlangsamt, ich kann im schlimmsten Fall sogar nicht richtig blättern (weil jedes Mal, wenn eine Zeile angezeigt wird, ein neuer CountDownTimer erstellt wird).

Ich suchte viel nach einer besseren Lösung, aber niemand war befriedigend.

Gibt es eine sauberere und glattere Lösung, um mehrere Countdown-Timer in einem ListView zu behandeln?

Vielen Dank

   

Anstatt zu versuchen, die verbleibende Zeit für alle zu zeigen, besteht die Idee darin, die verbleibende Zeit für die sichtbaren Elemente zu aktualisieren.

Bitte folgen Sie dem folgenden Beispielcode und lassen Sie mich wissen:

Hauptaktivität :

public class MainActivity extends Activity { private ListView lvItems; private List lstProducts; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lvItems = (ListView) findViewById(R.id.lvItems); lstProducts = new ArrayList<>(); lstProducts.add(new Product("A", System.currentTimeMillis() + 10000)); lstProducts.add(new Product("B", System.currentTimeMillis() + 20000)); lstProducts.add(new Product("C", System.currentTimeMillis() + 20000)); lstProducts.add(new Product("D", System.currentTimeMillis() + 20000)); lstProducts.add(new Product("E", System.currentTimeMillis() + 20000)); lstProducts.add(new Product("F", System.currentTimeMillis() + 20000)); lstProducts.add(new Product("G", System.currentTimeMillis() + 30000)); lstProducts.add(new Product("H", System.currentTimeMillis() + 20000)); lstProducts.add(new Product("I", System.currentTimeMillis() + 20000)); lstProducts.add(new Product("J", System.currentTimeMillis() + 40000)); lstProducts.add(new Product("K", System.currentTimeMillis() + 20000)); lstProducts.add(new Product("L", System.currentTimeMillis() + 50000)); lstProducts.add(new Product("M", System.currentTimeMillis() + 60000)); lstProducts.add(new Product("N", System.currentTimeMillis() + 20000)); lstProducts.add(new Product("O", System.currentTimeMillis() + 10000)); lvItems.setAdapter(new CountdownAdapter(MainActivity.this, lstProducts)); } private class Product { String name; long expirationTime; public Product(String name, long expirationTime) { this.name = name; this.expirationTime = expirationTime; } } public class CountdownAdapter extends ArrayAdapter { private LayoutInflater lf; private List lstHolders; private Handler mHandler = new Handler(); private Runnable updateRemainingTimeRunnable = new Runnable() { @Override public void run() { synchronized (lstHolders) { long currentTime = System.currentTimeMillis(); for (ViewHolder holder : lstHolders) { holder.updateTimeRemaining(currentTime); } } } }; public CountdownAdapter(Context context, List objects) { super(context, 0, objects); lf = LayoutInflater.from(context); lstHolders = new ArrayList<>(); startUpdateTimer(); } private void startUpdateTimer() { Timer tmr = new Timer(); tmr.schedule(new TimerTask() { @Override public void run() { mHandler.post(updateRemainingTimeRunnable); } }, 1000, 1000); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); convertView = lf.inflate(R.layout.list_item, parent, false); holder.tvProduct = (TextView) convertView.findViewById(R.id.tvProduct); holder.tvTimeRemaining = (TextView) convertView.findViewById(R.id.tvTimeRemaining); convertView.setTag(holder); synchronized (lstHolders) { lstHolders.add(holder); } } else { holder = (ViewHolder) convertView.getTag(); } holder.setData(getItem(position)); return convertView; } } private class ViewHolder { TextView tvProduct; TextView tvTimeRemaining; Product mProduct; public void setData(Product item) { mProduct = item; tvProduct.setText(item.name); updateTimeRemaining(System.currentTimeMillis()); } public void updateTimeRemaining(long currentTime) { long timeDiff = mProduct.expirationTime - currentTime; if (timeDiff > 0) { int seconds = (int) (timeDiff / 1000) % 60; int minutes = (int) ((timeDiff / (1000 * 60)) % 60); int hours = (int) ((timeDiff / (1000 * 60 * 60)) % 24); tvTimeRemaining.setText(hours + " hrs " + minutes + " mins " + seconds + " sec"); } else { tvTimeRemaining.setText("Expired!!"); } } } } 

activity_main.xml:

 < ?xml version="1.0" encoding="utf-8"?>    

list_item.xml

 < ?xml version="1.0" encoding="utf-8"?>     

Es könnte spät sein, aber das ist RecyclerView-Version mit PHP und JSON basierend auf hervorragende Antwort von @Eldhose M Babu. Hoffe, hilfreich zu sein 🙂

Mehrfache Countdown-Fotoanzeige

Adapter.java

  public class Adapter extends RecyclerView.Adapter { private Context context; private final List lstHolders; public List lst; private Handler mHandler = new Handler(); private Runnable updateRemainingTimeRunnable = new Runnable() { @Override public void run() { synchronized (lstHolders) { long currentTime = System.currentTimeMillis(); for (ViewHolder holder : lstHolders) { holder.updateTimeRemaining(currentTime); } } } }; public Adapter(List lst, Context context){ super(); this.lst = lst; this.context = context; lstHolders = new ArrayList<>(); startUpdateTimer(); } private void startUpdateTimer() { Timer tmr = new Timer(); tmr.schedule(new TimerTask() { @Override public void run() { mHandler.post(updateRemainingTimeRunnable); } }, 1000, 1000); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list, parent, false); ViewHolder viewHolder = new ViewHolder(v); return viewHolder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { holder.setData(lst.get(position)); synchronized (lstHolders) { lstHolders.add(holder); } holder.updateTimeRemaining(System.currentTimeMillis()); } @Override public int getItemCount() { return lst.size(); } class ViewHolder extends RecyclerView.ViewHolder{ public TextView textViewName; public TextView tvTimeRemaining; Model mModel; public void setData(Model item) { mModel = item; textViewName.setText(item.name); updateTimeRemaining(System.currentTimeMillis()); } public void updateTimeRemaining(long currentTime) { long timeDiff = mModel.expirationTime - currentTime; if (timeDiff > 0) { int seconds = (int) (timeDiff / 1000) % 60; int minutes = (int) ((timeDiff / (1000 * 60)) % 60); int hours = (int) ((timeDiff / (1000 * 60 * 60)) % 24); tvTimeRemaining.setText(hours + " hrs " + minutes + " mins " + seconds + " sec"); } else { tvTimeRemaining.setText("Expired!!"); } } public ViewHolder(View itemView) { super(itemView); tvTimeRemaining = (TextView) itemView.findViewById(R.id.cd); textViewName = (TextView) itemView.findViewById(R.id.textViewName); } } } 

Hauptaktivität.java

 public class MainActivity extends AppCompatActivity { private List lst; private RecyclerView recyclerView; private RecyclerView.LayoutManager layoutManager; private RecyclerView.Adapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); recyclerView = (RecyclerView) findViewById(R.id.recyclerView); recyclerView.setHasFixedSize(true); layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); lst = new ArrayList<>(); getData(); 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(); } }); } private void getData(){ final ProgressDialog loading = ProgressDialog.show(this,"Loading Data", "Please wait...",false,false); JsonArrayRequest jsonArrayRequest = new JsonArrayRequest("http://192.168.200.102/api.php", new Response.Listener() { @Override public void onResponse(JSONArray response) { loading.dismiss(); parseData(response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }); RequestQueue requestQueue = Volley.newRequestQueue(this); requestQueue.add(jsonArrayRequest); } private void parseData(JSONArray array){ for(int i = 0; i 

Modell.java

 public class Model { public String name; public long expirationTime; public long getexpirationTime() { return expirationTime; } public void setexpirationTime(long expire) { this.expirationTime = expire; } public String getName() { return name; } public void setName(String name) { this.name = name; }} 

activity_main.xml

 < ?xml version="1.0" encoding="utf-8"?>        

content_main.xml

 < ?xml version="1.0" encoding="utf-8"?>     

list.xml

 < ?xml version="1.0" encoding="utf-8"?>                 

und für die URL können Sie etwas tun:

 < ?php $arr = array( array( 'name' => "Android", 'expirationTime' => 1456860322 * 1000, // timestamp multiply for display in milliseconds ), array( 'name' => "Android 2", 'expirationTime' => 1456900522 * 1000, ), array( 'name' => "Android 3", 'expirationTime' => 1459509819 * 1000, ), array( 'name' => "Android 4", 'expirationTime' => 1457021950 * 1000, ), ); echo json_encode($arr); 

Bitte schauen Sie sich diesen Countdown-Timer im Listenansicht-Android- Beispiel an.

Benutzerdefinierter Adapter

 import android.os.CountDownTimer; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.ArrayList; public class Adapter extends RecyclerView.Adapter{ private ArrayList al_data; public class MyViewHolder extends RecyclerView.ViewHolder { public TextView tv_timer; CountDownTimer timer; public MyViewHolder (View view){ super(view); tv_timer = (TextView)view.findViewById(R.id.tv_timer); } } public Adapter(ArrayList al_data) { this.al_data = al_data; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_layout,parent,false); return new MyViewHolder(view); } @Override public void onBindViewHolder(final MyViewHolder holder, int position) { holder.tv_timer.setText(al_data.get(position)); if (holder.timer != null) { holder.timer.cancel(); } long timer = Long.parseLong(al_data.get(position)); timer = timer*1000; holder.timer = new CountDownTimer(timer, 1000) { public void onTick(long millisUntilFinished) { holder.tv_timer.setText("" + millisUntilFinished/1000 + " Sec"); } public void onFinish() { holder.tv_timer.setText("00:00:00"); } }.start(); } @Override public int getItemCount() { return al_data.size(); } } 

Hauptaktivität

 package com.androidsolutionworld.multipletimer; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.widget.LinearLayout; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private ArrayList al_data = new ArrayList<>(); private Adapter obj_adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RecyclerView)findViewById(R.id.recycler_view); al_data.add("1234"); al_data.add("1257"); al_data.add("100"); al_data.add("1547"); al_data.add("200"); al_data.add("500"); al_data.add("2000"); al_data.add("1000"); obj_adapter = new Adapter(al_data); LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.VERTICAL,false); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(obj_adapter); } } 

Vielen Dank

Adapterklasse: –


Öffentliche class CountdownAdapter erweitert RecyclerView.Adapter {ArrayList mList; Kontext mContext;

 public CountdownAdapter(ArrayList mList, Context mContext) { this.mList = mList; this.mContext = mContext; } public class ViewHolder extends RecyclerView.ViewHolder { CountDownTimer timerCount; TextView mCountDownTxt; public ViewHolder(View convertView) { super(convertView); mCountDownTxt = (TextView)convertView.findViewById(R.id.countdown_text); } } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return null; } @Override public void onBindViewHolder(final ViewHolder holder, final int position) { if(holder.timerCount==null) { holder.timerCount = new CountDownTimer(mList.get(position), 1000) { @Override public void onTick(long millis) { String hms = String.format("%02d:%02d", TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)), TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))); holder.mCountDownTxt.setText(hms); } @Override public void onFinish() { } }; } holder.mCountDownTxt.setVisibility(View.VISIBLE); holder.timerCount.start(); } @Override public int getItemCount() { return mList.size(); } 

}