Java 暂停更新UI元素的可运行程序

Java 暂停更新UI元素的可运行程序,java,android,multithreading,listview,android-listview,Java,Android,Multithreading,Listview,Android Listview,嗯,我遇到了一个我似乎无法解决的问题,我正在寻求一些帮助或替代解决方案。简而言之,我正在制作一个应用程序,让你可以在田径比赛、游泳比赛、体育课等比赛中使用多个秒表。我拥有基本功能,但似乎无法暂停我用作秒表的跑步表。我使用的是listview,当我尝试使用wait/notify停止暂停runnable时,整个活动都会冻结并最终崩溃 我使用的方法是暂停此答案中的runnables: 这是将runnables用作列表视图项的问题,还是runnables的实际暂停?它是可修复的还是有更好的方法来模拟秒表

嗯,我遇到了一个我似乎无法解决的问题,我正在寻求一些帮助或替代解决方案。简而言之,我正在制作一个应用程序,让你可以在田径比赛、游泳比赛、体育课等比赛中使用多个秒表。我拥有基本功能,但似乎无法暂停我用作秒表的跑步表。我使用的是listview,当我尝试使用wait/notify停止暂停runnable时,整个活动都会冻结并最终崩溃

我使用的方法是暂停此答案中的runnables: 这是将runnables用作列表视图项的问题,还是runnables的实际暂停?它是可修复的还是有更好的方法来模拟秒表功能?提前谢谢

Stopwatch.java

import android.os.Handler;
import android.os.SystemClock;
import android.widget.TextView;

public class Stopwatch implements Runnable{

private long startTime;
private long timeInMillis = 0L;
private long timeSwap = 0L;
private long totalTime = 0L;
private long lastTime = 0L;
private long lastSplit = 0L;
private boolean startTimeSet = false;
private String currentTime = "00:00:00";
private TextView totalTimeText;
private TextView lastTimeText;
private TextView lastSplitText;
private Handler handler;
private boolean paused = false;
private Object pauseLock;

public Stopwatch(TextView totalTimeText, TextView lastTimeText, TextView lastSplitText) {
    this.handler = new Handler();
    pauseLock = new Object();
    this.totalTimeText = totalTimeText;
    this.lastTimeText = lastTimeText;
    this.lastSplitText = lastSplitText;

}

@Override
public void run() {

    if(!startTimeSet) {
        startTime = SystemClock.uptimeMillis();
        startTimeSet = true;
    }

        timeInMillis = SystemClock.uptimeMillis() - startTime;
        totalTime = timeSwap + timeInMillis;


        totalTimeText.setText(TimeHelpers.millisToStringTime(totalTime));

        handler.postDelayed(this, 0);


    synchronized (pauseLock) {
        while (paused) {
            try {
                pauseLock.wait();
            } catch (InterruptedException e) {
            }
        }
    }




}

public void split() {
    lastSplit = getTotalTime() - lastTime;
    lastTime = getTotalTime();
    lastSplitText.setText(TimeHelpers.millisToStringTime(lastSplit));
    lastTimeText.setText(TimeHelpers.millisToStringTime(lastTime));
}

public String getCurrentTime() {
    return currentTime;
}

public long getTimeSwap() {
    return timeSwap;
}

public void setTimeSwap(long timeSwap) {
    this.timeSwap = timeSwap;
}

public long getTimeInMillis() {
    return timeInMillis;
}

public long getTotalTime() {
    return totalTime;
}

public void toggleStartTimeSet() {
    startTimeSet = !startTimeSet;
}

public void pause() {
    synchronized (pauseLock) {
        paused = true;
    }
}

public void resume() {
    synchronized (pauseLock) {
        paused = false;
        pauseLock.notify();
    }
}



}
包含listview的AthleteActivity.java

import java.util.ArrayList;
import java.util.Calendar;

import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

public class AthletesActivity extends Activity {

private ArrayList<Athlete> athletes;
private AthletesAdapter athletesAdapter;
private Button startStopAllButton;
private Button splitResetAllButton;
private ListView lv;
private ButtonStates splitResetState;
private ButtonStates startStopState;
private boolean running;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    setContentView(R.layout.activity_athletes);
    athletes = new ArrayList<Athlete>();
    startStopState = ButtonStates.START;
    running = false;
    splitResetState = ButtonStates.RESET;
    athletesAdapter = new AthletesAdapter(this,athletes);
    startStopAllButton = (Button) findViewById(R.id.btnStartStopAll);
    splitResetAllButton = (Button) findViewById(R.id.btnSplitResetAll);
    startStopAllButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            switch (startStopState) {
                case START:
                    startStopState = ButtonStates.STOP;
                    startStopAllButton.setText("Stop All");
                    splitResetState = ButtonStates.SPLIT;
                    splitResetAllButton.setText("Split All");
                    for(Athlete athlete : athletes) {
                        if(athlete.getPaused()) {
                            athlete.resume();
                        }
                        else athlete.start();
                    }
                    break;
                case STOP:
                    startStopState = ButtonStates.START;
                    startStopAllButton.setText("Start All");
                    splitResetState = ButtonStates.RESET;
                    splitResetAllButton.setText("Reset All");
                    for(Athlete athlete : athletes) {
                        athlete.pause();
                    }
                    break;
            }

        }
    });

    splitResetAllButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            switch(splitResetState) {
                case SPLIT:
                    for(Athlete athlete : athletes) {
                        athlete.split();
                    }
                    break;
                case RESET:
                    break;
            }
        }
    });

    lv = (ListView)findViewById(R.id.athleteList);
    lv.setAdapter(athletesAdapter);
    lv.setDivider(new ColorDrawable(0xff33b5e5));
    lv.setDividerHeight(3);
    lv.setBackgroundColor(0x222222);
    //set meet name
    Intent intent = getIntent();
    String eventName = intent.getStringExtra("Event");
    TextView eventNameText = (TextView) findViewById(R.id.event_name_athletes);
    eventNameText.setText(eventName);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu items for use in the action bar
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.athletes, menu);
    return super.onCreateOptionsMenu(menu);
}


@Override
public void onBackPressed() {
    super.onBackPressed();
    overridePendingTransition(R.anim.left_to_right, R.anim.right_to_left);
}

public boolean onOptionsItemSelected(MenuItem item) {
    // Handle presses on the action bar items
    switch (item.getItemId()) {
        case R.id.action_newAthlete:
            athletes.add(new Athlete("Athlete Name"));
            athletesAdapter.notifyDataSetChanged();
            //openNewAthleteDialog();
            return true;
        case R.id.action_discardAthlete:
            if(!athletes.isEmpty()) {
                //openDiscardEventDialog();
            }
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

public void openNewAthleteDialog() {
    AlertDialog.Builder builder = new AlertDialog.Builder(AthletesActivity.this, AlertDialog.THEME_HOLO_DARK);

    // Setting Dialog Title
    builder.setTitle("New Athlete");

    // Setting Dialog Message
    builder.setMessage("Enter Meet Name:");
    final EditText input = new EditText(AthletesActivity.this);  
    input.setTextColor(Color.WHITE);
    input.setHint("Athlete Name");
    LinearLayout layout = new LinearLayout(this);
    layout.setOrientation(LinearLayout.VERTICAL);
    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                          LinearLayout.LayoutParams.MATCH_PARENT,
                          LinearLayout.LayoutParams.WRAP_CONTENT);
    lp.setMargins(30, 0, 30, 0);
    layout.addView(input, lp);
    builder.setView(layout);



    // Setting Positive "Yes" Button
    builder.setPositiveButton("Add",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog,int which) {
                    athletes.add(new Athlete(input.getText().toString()));
                    athletesAdapter.notifyDataSetChanged();
                }});
    // Setting Negative "NO" Button
    builder.setNegativeButton("Cancel",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    // Write your code here to execute after dialog
                    dialog.cancel();
                }
            });

    // closed

    // Showing Alert Message
    AlertDialog dialog = builder.show();
    TextView messageText = (TextView)dialog.findViewById(android.R.id.message);
    messageText.setGravity(Gravity.CENTER);
    dialog.show();
}

}

更新UI的可运行程序可能不会暂停。@AlexeiKaigorodov-您能建议一种替代方法吗?这是有可能的,很多应用程序都有依赖于后台线程的UI元素,这可能会有帮助吗?
import java.util.ArrayList;
import java.util.Calendar;

import android.content.Context;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class AthletesAdapter extends ArrayAdapter<Athlete>{
private final Context context;
private final ArrayList<Athlete> athletes;

public AthletesAdapter(Context context, ArrayList<Athlete> athletes) {
    super(context, R.layout.list_athletes, athletes);
    this.context = context;
    this.athletes= athletes;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) context
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    View rowView = inflater.inflate(R.layout.list_athletes, parent, false);
    final int i = position;
    rowView.setBackgroundColor(0x222222);
    final AutoResizeEditTextView athleteNameText = (AutoResizeEditTextView) rowView.findViewById(R.id.athlete_name);
    athleteNameText.setEnabled(true);
    athleteNameText.setFocusableInTouchMode(true);
    athleteNameText.setFocusable(true);
    athleteNameText.setMovementMethod(null);
    athleteNameText.setText(athletes.get(position).getAthleteName());
    athleteNameText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {

        }

        @Override
        public void afterTextChanged(Editable editable) {
            athletes.get(i).setAthleteName(editable.toString());
            athleteNameText.setCursorVisible(false);
        }
    });
    TextView totalTimeText = (TextView) rowView.findViewById(R.id.main_time);
    TextView lastSplitText = (TextView) rowView.findViewById(R.id.split_time);
    TextView lastTimeText = (TextView) rowView.findViewById(R.id.second_time);


    athletes.get(position).setTextViews(totalTimeText, lastTimeText, lastSplitText);

    final Button startStopButton = (Button) rowView.findViewById(R.id.btnstartStop);
    final Button splitResetButton = (Button) rowView.findViewById(R.id.btnSplitReset);

    startStopButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Athlete athlete = athletes.get(i);
            switch(athlete.getStartStopButtonState()) {
                case START:
                    athlete.setStartStopButtonState(ButtonStates.STOP);
                    startStopButton.setText("Stop");
                    athlete.setSplitResetButtonState(ButtonStates.SPLIT);
                    splitResetButton.setText("Split");
                    if(athlete.getPaused()) {
                        athlete.resume();
                    }
                    else {
                        athlete.start();
                    }
                    break;
                case STOP:
                    athlete.setStartStopButtonState(ButtonStates.START);
                    startStopButton.setText("Start");
                    athlete.setSplitResetButtonState(ButtonStates.RESET);
                    splitResetButton.setText("Reset");
                    athlete.pause();
                    break;
            }
        }
    });
    splitResetButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Athlete athlete = athletes.get(i);
            switch(athlete.getSplitResetButtonState()) {
                case SPLIT:
                    athlete.split();
                    break;
                case RESET:
                    break;
            }

        }
    });

    return rowView;
}


}
import android.os.Handler;
import android.widget.TextView;

public class Athlete {

private String athleteName;
private Stopwatch sw;
private Handler swHandler;
private TextView totalTimeText;
private boolean paused = false;
private boolean running = false;
private ButtonStates startStopButtonState;
private ButtonStates splitResetButtonState;

public Athlete(String athleteName) {
    this.athleteName = athleteName;
    startStopButtonState = ButtonStates.START;
    splitResetButtonState = ButtonStates.RESET;
}

public String getAthleteName() {
    return athleteName;
}

public void setAthleteName(String athleteName) {
    this.athleteName = athleteName;
}

public void setStopwatch(Stopwatch sw) {
    this.sw = sw;
}

public Stopwatch getStopwatch() {
    return sw;
}

public void start() {
    sw.run();
    running = true;
}

public void split() {
    sw.split();
}

public void setTextViews(TextView totalTimeText, TextView lastTimeText, TextView splitTimeText) {
    this.totalTimeText = totalTimeText;
    setStopwatch(new Stopwatch(totalTimeText, lastTimeText, splitTimeText));
}

public void pause() {
    this.paused = true;
    sw.pause();
}

public void resume() {
    this.paused = false;
    sw.resume();
}

public boolean getPaused() {
    return paused;
}

public ButtonStates getStartStopButtonState() {
    return startStopButtonState;
}

public void setStartStopButtonState(ButtonStates state) {
    this.startStopButtonState = state;
}

public ButtonStates getSplitResetButtonState() {
    return splitResetButtonState;
}

public void setSplitResetButtonState(ButtonStates state) {
    this.splitResetButtonState = state;
}

private boolean getRunning() {
    return running;
}


}