Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android正在创建多个倒计时计时器不工作的listview_Java_Android_Listview_Timer_Countdown - Fatal编程技术网

Java Android正在创建多个倒计时计时器不工作的listview

Java Android正在创建多个倒计时计时器不工作的listview,java,android,listview,timer,countdown,Java,Android,Listview,Timer,Countdown,我是android新手。目前,我在尝试在listfragment类中的listview中的每个项目中创建倒计时计时器时遇到问题。计时器没有倒计时,它在那里被卡住了。有人能帮我找出我的问题吗 这是我的listview类 public class OneFragment extends ListFragment { View rootView; TextView scheduleId; ListAdapter listadapter; @Override public void onActivit

我是android新手。目前,我在尝试在listfragment类中的listview中的每个项目中创建倒计时计时器时遇到问题。计时器没有倒计时,它在那里被卡住了。有人能帮我找出我的问题吗

这是我的listview类

public class OneFragment extends ListFragment {

View rootView;
TextView scheduleId;
ListAdapter listadapter;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    final DBController controller = new DBController(getActivity());
    final ArrayList<HashMap<String, String>> scheduleList = controller.getAllSchedules();
    if (scheduleList.size()!=0){
        ListView lv = getListView();
        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                scheduleId = (TextView) view.findViewById(R.id.scheduleId);
                String getId = scheduleId.toString();
                int duration = Toast.LENGTH_SHORT;
                Toast toast = Toast.makeText(getActivity(), getId, duration);
                toast.show();
                controller.deleteSchedule(getId);
                onResume();
            }
        });
        ArrayList schedule = new ArrayList();
        schedule.clear();
        String query = "SELECT  * FROM schedules";
        Cursor c1 = controller.selectQuery(query);
        if (c1 != null & c1.getCount() != 0) { //if there is item in the cursor
            if (c1.moveToFirst()) {  //start to move to position
                do {
                    getSchedule schedule1 = new getSchedule();  //create object of the class getParticipant
                    schedule1.setscheduleId(c1.getString(c1
                            .getColumnIndex("scheduleId")));  //set the friend id in the object
                    schedule1.setscheduleName(c1.getString(c1
                            .getColumnIndex("scheduleName")));  //set the friend name in the object
                    schedule1.setscheduleDuration(c1.getString(c1.getColumnIndex("scheduleDuration")));
                    schedule.add(schedule1);  //add the object to arraylist
                } while (c1.moveToNext());  //if still have item in the cursor, loop again
            }
        }
        c1.close();
        listadapter = new ListAdapter(getActivity(), schedule);//create object of adapter class by
        //passing a context and arraylist
        listadapter.notifyDataSetChanged();
        setListAdapter(listadapter);  //set the adapter

    }
}

Handler handler = new Handler();
Runnable updateRunnable= new Runnable() {
    @Override
    public void run() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {  listadapter.notifyDataSetChanged();     }
        });
        handler.postDelayed(this, 1000);
    }
};

@Override
public void onResume() {   //when user resume from an intent
    super.onResume();
    handler.post(updateRunnable);
    if (getListView() != null) {   //if the list view is not null
        updateData();     //call the method updateData() to update the listView
    }
}

@Override
public void onStop() {
    super.onStop();
    handler.removeCallbacks(updateRunnable);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    rootView = inflater.inflate(R.layout.fragment_one, container, false);
    return rootView;
}

public void updateData(){
    final DBController controller = new DBController(getActivity());
    final ArrayList<HashMap<String, String>> scheduleList = controller.getAllSchedules();
    if (scheduleList.size()!=0){
        ListView lv = getListView();
        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                scheduleId = (TextView) view.findViewById(R.id.scheduleId);
                String getId = scheduleId.toString();
                int duration = Toast.LENGTH_SHORT;
                Toast toast = Toast.makeText(getActivity(), getId, duration);
                toast.show();
                controller.deleteSchedule(getId);
                onResume();
            }
        });
        ArrayList schedule = new ArrayList();
        schedule.clear();
        String query = "SELECT  * FROM schedules";
        Cursor c1 = controller.selectQuery(query);
        if (c1 != null & c1.getCount() != 0) { //if there is item in the cursor
            if (c1.moveToFirst()) {  //start to move to position
                do {
                    getSchedule schedule1 = new getSchedule();  //create object of the class getParticipant
                    schedule1.setscheduleId(c1.getString(c1
                            .getColumnIndex("scheduleId")));  //set the friend id in the object
                    schedule1.setscheduleName(c1.getString(c1
                            .getColumnIndex("scheduleName")));  //set the friend name in the object
                    schedule1.setscheduleDuration(c1.getString(c1.getColumnIndex("scheduleDuration")));
                    schedule.add(schedule1);  //add the object to arraylist
                } while (c1.moveToNext());  //if still have item in the cursor, loop again
            }
        }
        c1.close();
        ListAdapter listadapter = new ListAdapter(getActivity(), schedule);//create object of adapter class by
        //passing a context and arraylist
        listadapter.notifyDataSetChanged();
        setListAdapter(listadapter);  //set the adapter
    }
}
}
我试图检索数据库中每个项目的持续时间(以分钟为单位),并为listview中的每个项目创建一个倒计时计时器。但是计时器在那里失灵了…请帮帮我。谢谢。

使用更新的适配器

public class ListAdapter extends BaseAdapter {
    Context ctx;
    private CountDownTimer countDownTimer;
    private long countdown;
    private TextView scheduleDuration;
    LayoutInflater lInflater;
    private Handler mHandler = new Handler();
    ArrayList<getSchedule> objects;
    private String Duration = "";
    boolean flag = true;
    ListAdapter(Context context, ArrayList<getSchedule> scheduleList) {
        ctx = context;  //set the context
        objects = scheduleList; //set the arraylist
        lInflater = (LayoutInflater) ctx  //set the layout
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        return objects.size();
    }

    @Override
    public Object getItem(int position) {
        return objects.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        getSchedule schedule = objects.get(position);
        final DBController controller = new DBController(ctx);
        View view = convertView;
        if (view == null) {  //if view is null
            view = lInflater.inflate(R.layout.view_schedule_entry, parent, false);
        }
        final TextView scheduleId = (TextView)view.findViewById(R.id.scheduleId);
        scheduleId.setText(schedule.getscheduleId());
        TextView scheduleName = (TextView)view.findViewById(R.id.scheduleName);
        scheduleName.setText(schedule.getscheduleName());
        scheduleDuration = (TextView)view.findViewById(R.id.scheduleDuration);
        scheduleDuration.setText(Duration);
        int convert = Integer.parseInt(schedule.getscheduleDuration());
        countdown = 60 * convert * 1000;
        if(flag){
            startTimer();
            flag = false;
        }
        return view;
    }

    private void startTimer() {

        countDownTimer = new CountDownTimer(countdown, 500) {
            // 500 means, onTick function will be called at every 500
            // milliseconds

            @Override
            public void onTick(long leftTimeInMilliseconds) {
                long seconds = leftTimeInMilliseconds / 1000;

                Duration =String.format("%02d:%02d:%02d", seconds / 3600,
                        (seconds % 3600) / 60, (seconds % 60));
                // format the textview to show the easily readable format
                notifyDataSetChanged();

            }

            @Override
            public void onFinish() {
                // this function will be called when the timecount is finished
                Duration = "Time up!";
                notifyDataSetChanged();
            }

        }.start();

    }
}
公共类ListAdapter扩展了BaseAdapter{
上下文ctx;
私人倒计时;
私人长倒计时;
私有文本视图计划持续时间;
拉平机;
私有处理程序mHandler=新处理程序();
阵列列表对象;
私有字符串持续时间=”;
布尔标志=真;
ListAdapter(上下文上下文,ArrayList scheduleList){
ctx=context;//设置上下文
objects=scheduleList;//设置arraylist
lInflater=(LayoutInflater)ctx//设置布局
.getSystemService(上下文布局\充气机\服务);
}
@凌驾
public int getCount(){
返回objects.size();
}
@凌驾
公共对象getItem(int位置){
返回对象。获取(位置);
}
@凌驾
公共长getItemId(int位置){
返回位置;
}
@凌驾
公共视图getView(int位置、视图转换视图、视图组父视图){
getSchedule=objects.get(位置);
最终DBController=新DBController(ctx);
视图=转换视图;
if(view==null){//if视图为null
视图=lInflater.充气(R.layout.view\u schedule\u entry,parent,false);
}
final TextView scheduleId=(TextView)view.findViewById(R.id.scheduleId);
scheduleId.setText(schedule.getscheduleId());
TextView scheduleName=(TextView)view.findViewById(R.id.scheduleName);
scheduleName.setText(schedule.getscheduleName());
scheduleDuration=(TextView)view.findViewById(R.id.scheduleDuration);
scheduleDuration.setText(持续时间);
int convert=Integer.parseInt(schedule.getscheduleDuration());
倒计时=60*convert*1000;
国际单项体育联合会(旗){
startTimer();
flag=false;
}
返回视图;
}
私有void startTimer(){
倒计时=新倒计时(倒计时,500){
//500表示每500次调用一次onTick函数
//毫秒
@凌驾
公共void onTick(长LeftTimein毫秒){
长秒=LeftTimein毫秒/1000;
持续时间=字符串。格式(“%02d:%02d:%02d”),秒/3600,
(秒数%3600)/60,(秒数%60));
//格式化文本视图以显示易于阅读的格式
notifyDataSetChanged();
}
@凌驾
公共无效onFinish(){
//时间计数完成后将调用此函数
Duration=“时间到了!”;
notifyDataSetChanged();
}
}.start();
}
}

每次加载视图时都会启动计时器。这意味着,如果在listview中上下滚动几次,最终可能会在后台运行数百次。非常糟糕。此外,您没有使用ViewHolder。您应该使用一个,它将大大提高性能。除此之外,我认为正确的方法如下。(我最近也做了同样的事情)

getSchedule对象应该有一个函数,用于计算该倒计时还剩多少时间:

public function String getTimeLeft(){
   String timeLeft;
   .
   .
   return timeLeft; 
}
在适配器的getView方法中,执行以下操作:

  timeLeftTextView.setText(getSchedule.getTimeLeft());
在你的活动中

// class variables
Handler handler = new Handler(); 
Runnable updateRunnable= new Runnable() {
    @Override
    public void run() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {  adapter.notifyDataSetChanged();     }
        });
        handler.postDelayed(this, 1000);
    }
};

@Override
protected void onResume() { 
    super.onResume(); 
    handler.postRunnable(updateRunnable);
}

@Override
protected void onStop() { 
    super.onStop(); 
    handler.removeCallbacks(updateRunnable);
}

不要忘记调用
handler.removeCallbacks(updateRunnable)

嗨,谢谢你的帮助。计时器现在正在移动,但它完全乱了。这就像进入一个多重循环。例如,它从59开始,然后是58,然后是59,58,57,58,57,56,59,58,59诸如此类……嗨,谢谢你的帮助。然而,它仍然受到阻碍。我已经按照您的指示进行了操作,我已经在我的getscheduleDuration类中包含了getscheduleDuration()函数。我已将持续时间转换为字符串并存储在getSchedule类中,然后在ListAdapter类中将其转换回整数。我已经更新了我的问题。你能检查一下我有没有做错什么吗?你没有照我说的做。您仍然在每次getView调用时启动计时器。我给你提供了另一个选择…处理器方法,而不是计时器。不是两个人同时在一起。如果您遵循我的方法,那么您的所有listview元素将只使用一个处理程序进行更新,而使用您的方法创建数百个计时器!除此之外,您没有正确实施计时器方法。ListView中的视图是循环使用的。你不能在后台线程中引用它们,否则你会像allready一样出现奇怪的行为。这会导致ListView“闪烁”,具体取决于你在其中的内容。(即,数据将不断从对象中重新加载)
  timeLeftTextView.setText(getSchedule.getTimeLeft());
// class variables
Handler handler = new Handler(); 
Runnable updateRunnable= new Runnable() {
    @Override
    public void run() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {  adapter.notifyDataSetChanged();     }
        });
        handler.postDelayed(this, 1000);
    }
};

@Override
protected void onResume() { 
    super.onResume(); 
    handler.postRunnable(updateRunnable);
}

@Override
protected void onStop() { 
    super.onStop(); 
    handler.removeCallbacks(updateRunnable);
}