2016-11-28 110 views
0

我试图在列表veiw实现中制作倒数计时器。每个列表项都有一个可以启动或停止的单独倒数计时器。但是我注意到,如果我在列表中添加第一个计时器并设置它的时间。当我启动计时器时,它会比实际时间少两秒钟。例如,如果我添加了12秒的倒数。然后它将从10开始计数。但是当倒计时发生时,我添加另一个新的计时器并设置它的时间,它会在确切的给定时间开始。只有当列表中没有其他计数器或所有计数器已停止且不计数时,新计数器才会在错误的时间开始。同样,只有在其他定时器正在倒计时时才会开始正确的时间。如果有人能帮我弄清楚问题在哪里,我会很感激。我一直在看代码几天。有时倒数计时器,在实际时间前计数2秒

这里是我的适配器类

public class CustomAdapterCounter extends ArrayAdapter<CounterData> { 

private final LayoutInflater mInflater; 
Context context; 
Uri sound = Uri.parse("android.resource://com.tattooalarmclock.free/" + R.raw.counter); 
String counterString = ""; 
private List<ViewHolder> lstHolders; 
private List<CounterData> list = new ArrayList<CounterData>(); 
private Handler mHandler = new Handler(); 
private Runnable updateRemainingTimeRunnable = new Runnable() { 
    @Override 
    public void run() { 
     synchronized (lstHolders) { 
      long currentTime = System.currentTimeMillis(); 
      for (ViewHolder holder : lstHolders) { 
       // if(!holder.counterData.isStopped) 
        holder.updateTimeRemaining(System.currentTimeMillis()); 
      } 
     } 
    } 
}; 

public CustomAdapterCounter(Context context, List<CounterData> l) { 
    super(context, 0, l); 
    this.context = context; 
    lstHolders = new ArrayList<>(); 
    list = l; 
    mInflater = LayoutInflater.from(context); 

    for(int i=0; i<list.size(); i++) { 
     CounterData[] array = list.toArray(new CounterData[list.size()]); 
     if(!array[i].isStopped) 
      startUpdateTimer(); 
    } 
} 

public double getScreenSize() { 
    DisplayMetrics dm = new DisplayMetrics(); 
    WindowManager windowManager = (WindowManager) context 
      .getSystemService(Context.WINDOW_SERVICE); 
    windowManager.getDefaultDisplay().getMetrics(dm); 
    int width = dm.widthPixels; 
    int height = dm.heightPixels; 
    int dens = dm.densityDpi; 
    double wi = (double) width/(double) dens; 
    double hi = (double) height/(double) dens; 
    double x = Math.pow(wi, 2); 
    double y = Math.pow(hi, 2); 
    double screenInches = Math.sqrt(x + y); 

    return screenInches; 
} 


private void startUpdateTimer() { 
    Timer tmr = new Timer(); 
    tmr.schedule(new TimerTask() { 
     @Override 
     public void run() { 
      mHandler.post(updateRemainingTimeRunnable); 
     } 
    }, 1000, 1000); 
} 

public static <T> List<T> stringToArray(String s, Class<T[]> clazz) { 
    T[] arr = new Gson().fromJson(s, clazz); 
    return Arrays.asList(arr); //or return Arrays.asList(new Gson().fromJson(s, clazz)); for a one-liner 
} 


public boolean getListSharedPreferences() { 

    SharedPreferences sharedPreferences = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE); 

    if (sharedPreferences.getString("CL", null) != null) { 
      counterString = sharedPreferences.getString("CL", null); 
      Gson gson = new Gson(); 
      TypeToken<List<CounterData>> token = new TypeToken<List<CounterData>>() {}; 
      list = gson.fromJson(counterString, token.getType()); 
     return true; 
    } 
    else 
     return false; 
} 

public void saveListSharedPreferences(List counterList) { 

    Gson gson = new Gson(); 
    counterString = gson.toJson(counterList); 
    SharedPreferences sharedPreferences = context.getSharedPreferences("com.example.app", Context.MODE_PRIVATE); 
    sharedPreferences.edit().putString("CL", counterString).commit(); 

} 

@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    ViewHolder holder = null; 

    if (convertView == null) { 
     holder = new ViewHolder(); 
     if(getScreenSize() <= 4) 
     convertView = mInflater.inflate(R.layout.list_view_counter_small, parent, false); 
     else 
     convertView = mInflater.inflate(R.layout.list_view_item_counter, parent, false); 
     holder.counterTextView = (TextView) convertView.findViewById(R.id.counterTextView); 
     holder.stopCounter = (Button) convertView.findViewById(R.id.counterStopInList); 
     holder.startCounter = (Button) convertView.findViewById(R.id.counterStartInList); 
     holder.deleteCounter = (Button) convertView.findViewById(R.id.deleteCounter); 
     convertView.setTag(holder); 
     synchronized (lstHolders) { 
      lstHolders.add(holder); 
     } 

    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 
    holder.setData2(getItem(position)); 

    final ViewHolder finalHolder = holder; 
    holder.stopCounter.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      long store = finalHolder.counterData.expirationTime - System.currentTimeMillis(); 
      finalHolder.counterData.isStopped = true; 
      finalHolder.counterData.expirationTime = store; 
      finalHolder.stopCounter.setEnabled(false); 
      finalHolder.stopCounter.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY); 
      finalHolder.startCounter.setEnabled(true); 
      finalHolder.startCounter.getBackground().setColorFilter(null); 
      list.set(position, finalHolder.counterData); 
      saveListSharedPreferences(list); 

     /*  if(getListSharedPreferences()) { 
       System.out.println("List before change in stop button " + list.toString()); 
       list = stringToArray(counterString, CounterData[].class); 
       list.set(position, finalHolder.counterData); 
       System.out.println("List before change in stop button " + list.toString()); 
       saveListSharedPreferences(list); 
      } 
      else { 
       System.out.println(list.toString()); 
       list.set(position, finalHolder.counterData); 
       System.out.println(list.toString()); 
       saveListSharedPreferences(list); 
      } 
     */ 
     } 
    }); 

    holder.startCounter.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      finalHolder.counterData.expirationTime = System.currentTimeMillis() + finalHolder.counterData.expirationTime; 
      finalHolder.counterData.isStopped = false; 
      //finalHolder.counterData.expirationTime = System.currentTimeMillis() + finalHolder.counterData.expirationTime; 
      //finalHolder.setData(finalHolder.counterData); 
      finalHolder.startCounter.setEnabled(true); 
      finalHolder.startCounter.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY); 
      finalHolder.stopCounter.setEnabled(true); 
      finalHolder.stopCounter.getBackground().setColorFilter(null); 
      list.set(position, finalHolder.counterData); 
      saveListSharedPreferences(list); 
      startUpdateTimer(); 
     /*  if(getListSharedPreferences()) { 
       list = stringToArray(counterString, CounterData[].class); 
       System.out.println("List before change in start button " + list.toString()); 
       list.set(position, finalHolder.counterData); 
       System.out.println("List after change in start button " + list.toString()); 
       saveListSharedPreferences(list); 
      } 
      else { 
       list.set(position, finalHolder.counterData); 
       saveListSharedPreferences(list); 
      } */ 
     } 
    }); 

    final ViewHolder finalHolder1 = holder; 
    holder.deleteCounter.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
/*   if(finalHolder1.mediaPlayer.isPlaying()) { 
       finalHolder.mediaPlayer.stop(); 
      //  finalHolder.counterData.isSoundPlayedBefore = true; 
      } */ 
      list.remove(position); 
      notifyDataSetChanged(); 
      saveListSharedPreferences(list); 
     } 
    }); 


    return convertView; 
} 
} 

class ViewHolder { 
public TextView counterTextView; 
//public List<Long> l; 
CounterData counterData; 
Button startCounter; 
Button stopCounter; 
Button deleteCounter; 
boolean stop = false; 
long timeDiff; 
// Context context; 
// MediaPlayer mediaPlayer; 
// List<CounterData> counterDataList; 

public void setData(CounterData item) { 
    counterData = item; 
    updateTimeRemaining(System.currentTimeMillis()); 
} 

public void setData2(CounterData item) { 
    counterData = item; 
    updateTimeRemaining(System.currentTimeMillis()); 
} 

public void updateTimeRemaining(long currentTime) { 

    if (!counterData.isStopped) { 
     timeDiff = counterData.expirationTime - currentTime; 
     //System.out.println("Time Diff Inside Method " + timeDiff); 
     if (timeDiff > 0) { 
      int seconds = (int) (timeDiff/1000) % 60; 
      int minutes = (int) ((timeDiff/(1000 * 60)) % 60); 
      int hours = (int) TimeUnit.MILLISECONDS.toHours(timeDiff); 
      counterTextView.setText(hours + "H " + minutes + "M " + seconds + "S"); 
      stopCounter.setEnabled(true); 
      stopCounter.getBackground().setColorFilter(null); 
      startCounter.setEnabled(false); 
      startCounter.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY); 
     } else { 
      counterTextView.setText("Times Up"); 
      startCounter.setEnabled(false); 
      startCounter.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY); 
      stopCounter.setEnabled(false); 
      stopCounter.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY); 
     // Vibrator v = (Vibrator) this.context.getSystemService(Context.VIBRATOR_SERVICE); 
      // Vibrate for 500 milliseconds 
     // v.vibrate(5000); 
    /*  if(!counterData.isSoundPlayedBefore) { 
       mediaPlayer.start(); 
       mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 
        @Override 
        public void onCompletion(MediaPlayer mp) { 
         mediaPlayer.stop(); 
        } 
       }); 
       counterData.isSoundPlayedBefore = true; 
       if(findIndex(counterData) != -1) { 
        int index = findIndex(counterData); 
        counterDataList.set(index,counterData); 
        saveListSharedPreferences(counterDataList); 
       } 
      } */ 
     } 
    } 
    else { 
     long store = counterData.expirationTime + System.currentTimeMillis() - currentTime; 
     int seconds = (int) (store/1000) % 60; 
     int minutes = (int) ((store/(1000 * 60)) % 60); 
     int hours = (int) TimeUnit.MILLISECONDS.toHours(store); 
     counterTextView.setText(hours + "H " + minutes + "M " + seconds + "S"); 
     startCounter.setEnabled(true); 
     startCounter.getBackground().setColorFilter(null); 
     stopCounter.setEnabled(false); 
     stopCounter.getBackground().setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY); 
    } 
} 
} 

这是我的CounterData类

class CounterData { 
long expirationTime; 
boolean isStopped; 
boolean isSoundPlayedBefore; 
int id; 

public CounterData(long expirationTime, int id) { 
    this.expirationTime = expirationTime; 
    isStopped = true; 
    isSoundPlayedBefore = false; 
    this.id = id; 
} 

public String toString() { 

    return String.valueOf("Remaining Time: " + TimeUnit.MILLISECONDS.toMinutes(this.expirationTime) + ":" + TimeUnit.MILLISECONDS.toSeconds(this.expirationTime)); 
} 

public void setCounterID(int id) { 
    this.id = id; 
} 

public int getCounterID() { 
    return this.id; 
} 

} 

而且我从一小时,分,秒的数量增加采摘的时间。

case R.id.counterStartStopButton: 
      long hour = TimeUnit.HOURS.toMillis(numberPickerHour.getValue()); 
      long minute = TimeUnit.MINUTES.toMillis(numberPickerMinute.getValue()); 
      long second = TimeUnit.SECONDS.toMillis(numberPickerSecond.getValue()); 
     //  if(getListSharedPreferences()) { 
       if(getCounterIDSharedPreferences()) { 
        counterID = counterID + 1; 
        list.add(new CounterData(hour + minute + second, counterID)); 
        saveCounterIDSharedPreferences(counterID); 
       } 
       else { 
        counterID = 1; 
        list.add(new CounterData(hour + minute + second, counterID)); 
        saveCounterIDSharedPreferences(counterID); 
       } 

UPDATE 这里的共享偏好代码

public void saveCounterIDSharedPreferences(int id) { 

    SharedPreferences sharedPreferences = this.getSharedPreferences("com.example.app", Context.MODE_PRIVATE); 
    sharedPreferences.edit().putInt("Counter ID123", id).commit(); 
} 


public boolean getCounterIDSharedPreferences() { 

    SharedPreferences sharedPreferences = this.getSharedPreferences("com.example.app", Context.MODE_PRIVATE); 

    if (sharedPreferences.getInt("Counter ID123", -1) != -1) { 
     counterID = sharedPreferences.getInt("Counter ID123", -1); 
     return true; 
    } 
    else 
     return false; 
} 
+0

所以,你的第一个计时器开始在10 (2秒延迟),但之后一切正常? – Hahn

+0

如果没有其他定时器或列表中的所有其他定时器都暂停,如果我添加新的定时器,它将从(实际时间-2秒)开始计数。如果列表中的其他计数器正在倒计时并且没有停止,并且在这种情况下如果我添加新的计数器,则它会正常启动。 –

+0

你可以发布CounterIdSharedPref代码吗? – Hahn

回答

0

什么横空出世,工作对我来说是改变定时器的任务如下:

private void startUpdateTimer() { 
    Timer tmr = new Timer(); 
    tmr.schedule(new TimerTask() { 
     @Override 
     public void run() { 
      mHandler.post(updateRemainingTimeRunnable); 
     } 
    }, 500, 500); 
}