我正在开发一个Android应用程序,其中包括秒表。
秒表本身功能正常。它使用Runnable来更新UI并显示时间。

 private Runnable updateTimerThread = new Runnable() {

    public void run() {

        timeInMilliseconds = SystemClock.uptimeMillis() - startTime;

        updatedTime = timeSwapBuff + timeInMilliseconds;

        int secs = (int) (updatedTime / 1000);
        int mins = secs / 60;
        secs = secs % 60;
        int milliseconds = (int) (updatedTime % 1000);

        if(mins > 99){
            return;
        }

        mChronoMinutes.setText(mins + "");
        mChronoSeconds.setText(String.format("%02d", secs));
        mChronoMiliseconds.setText(String.format("%03d", milliseconds));

        customHandler.postDelayed(this, 0);

    }
};


但是我想包括一个计时器。我有一个按钮,当按下该按钮时,会将当前时间添加到我的列表中,并通知我的列表适配器。
按钮的onClickListener中有一些逻辑,但我认为这没什么大不了的。
这是onClickListener:

View.OnClickListener mLapListener = new View.OnClickListener() {
    public void onClick(View v) {

        lapCounter++;

        int secs = (int) (updatedTime / 1000);
        int mins = secs / 60;
        secs = secs % 60;
        int milliseconds = (int) (updatedTime % 1000);

        //for laptime
        int lapSecs = (int) ((updatedTime - lastLapTime) / 1000);
        int lapMins = lapSecs / 60;
        lapSecs = lapSecs % 60;
        int lapMilliseconds = (int) ((updatedTime - lastLapTime) % 1000);

        laps.add(0, "# " + lapCounter + "   " + mins + " " + String.format("%02d", secs) + "," + String.format("%03d", milliseconds)
                + "   " + lapMins + " " + String.format("%02d", lapSecs) + "," + String.format("%03d", lapMilliseconds));

        adapter.notifyDataSetChanged();

        lapListView.post(new Runnable() {
            @Override
            public void run() {
                lapListView.smoothScrollToPosition(0);
            }
        });

        lastLapTime = updatedTime;

    }
};


如您所见,它获取当前时间和上一圈以来的时间,并将其显示在列表视图中。
这可以按预期工作,但是问题是,每当我按下圈按钮时,秒表本身便开始冻结,在第一圈中它几乎是不可见的,但是每当我按下按钮时,冻结就会变得更加明显。 20圈后,秒表将悬挂半秒左右。

我认为也许我在UI线程上做的工作太多了,所以我尝试使用AsyncTask在doInBackground中执行逻辑并在onPostExecute方法中更新listView。
但是,这没有任何区别,计时器在经过几圈后仍然开始冻结。

我是一个相当新的Android程序员,我真的不知道该怎么做或实际上是什么问题。
我希望有人可以帮助我!

我发现了另一件事,如果我开始足够快地单击圈按钮,那么最终它将FC并给我一个“致命信号6(SIGABRT)”,谷歌告诉我这与多线程相关。

提前致谢,
尼尔斯

编辑:

这是我使用过的asynctask,但是并没有改变任何东西。

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

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }
    @Override
    protected Void doInBackground(Void... params) {

        lapCounter++;

        secs = (int) (updatedTime / 1000);
        mins = secs / 60;
        secs = secs % 60;
        milliseconds = (int) (updatedTime % 1000);

        //for laptime
        lapSecs = (int) ((updatedTime - lastLapTime) / 1000);
        lapMins = lapSecs / 60;
        lapSecs = lapSecs % 60;
        lapMilliseconds = (int) ((updatedTime - lastLapTime) % 1000);

        lastLapTime = updatedTime;

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);


        laps.add(0, "# " + lapCounter + "   " + mins + " " + String.format("%02d", secs) + "," + String.format("%03d", milliseconds)
                + "   " + lapMins + " " + String.format("%02d", lapSecs) + "," + String.format("%03d", lapMilliseconds));

        adapter.notifyDataSetChanged();

        lapListView.post(new Runnable() {
            @Override
            public void run() {
                lapListView.smoothScrollToPosition(0);
            }
        });

    }

}


和我的ListAdapter:

public class LapListAdapter extends BaseAdapter {

private Context context;
private ArrayList<String> laps;

private int mSelectedItem;

public LapListAdapter(Context context, ArrayList<String> laps) {
    this.context = context;
    this.laps = laps;
}

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

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

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

public int getSelectedItem() {
    return mSelectedItem;
}

public void setSelectedItem(int selectedItem) {
    mSelectedItem = selectedItem;
}


@Override
public View getView(int position, View convertView, ViewGroup parent) {

    Holder holder = new Holder();

    if (convertView == null) {
        LayoutInflater mInflater = (LayoutInflater)
                context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        convertView = mInflater.inflate(R.layout.lap_item, null);


        convertView.setTag(holder);
    } else {

        holder = (Holder) convertView.getTag();
    }

    holder.lap_info = (TextView) convertView.findViewById(R.id.lap_info);

    Typeface roboto;

    roboto = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Bold.ttf");


    holder.lap_info.setText(laps.get(position));
    holder.lap_info.setTypeface(roboto);


    return convertView;
}

class Holder {

    TextView lap_info;

}


}

希望能帮助到你

最佳答案

我敢打赌,正是造成您问题的TypeFace.createFromAsset调用。尝试删除该行,看看会发生什么。

您应该能够在适配器的构造函数中创建该字体并将其重新用于getView()方法,而不是每次都在getView方法中重新创建它。

07-24 09:37
查看更多