使用Handler的多线程不会超过第一遍

时间:2013-12-11 01:39:14

标签: java android multithreading handler runnable

我正在尝试在我的活动中运行一个简单的时钟,该项目的目的是创建一个辅助线程来运行我们的时钟并使用处理程序更新我们的主UI线程。我以为我有它工作,但我想我看错了。无论哪种方式,这是我的代码

public class MainActivity extends Activity implements Runnable{

/** VARIABLES **/
private LinearLayout currView;
private TextView clock;
private Typeface icelandFace;
private Calendar cal;

// clock time values
private int clockMins;
private int clockHour;
private int timeOfDay;      // am/pm
private String currTimeString;

// for alarm clock
boolean startAlarm = false;
private long alarmStartTime = -1;
private final int DESIRED_ALARM_DURATION = 5;

// clock thread handler, to communicate between our main ui and our secondary ui
// - note to self - rather unclear on the explanation for the suppression for the handler
private Handler handler = new Handler();

// runnable variable for the secondary thread to actually run on
private final Runnable clockRunnable = new Runnable(){
    public void run(){
        updateUI();
    }
};


/** OVERRIDDEN CLASS METHODS **/
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    currView = (LinearLayout) findViewById(R.id.main_activity);
    clock = (TextView) findViewById(R.id.clock_view);
    clock.setTextSize(clock.getTextSize() * 2);
    icelandFace = Typeface.createFromAsset(getAssets(), "font/Iceland-Regular.ttf");
    clock.setTypeface(icelandFace);

    cal = Calendar.getInstance();

    // Create New Thread (to run our clock on)
    Thread clockThread = new Thread(){
        public void run() {         
            keepTime();
            clockMins = cal.get(Calendar.MINUTE);

            clockHour = cal.get(Calendar.HOUR);
            timeOfDay = cal.get(Calendar.AM_PM);

            // Implement the handler for the thread
            // NOTE: recall, Message contains data and is passed to our handler
            //Message message = handler.obtainMessage();
                Bundle bundle = new Bundle();
                 // start with hours
                String timeString = clockHour + ":";
                // add minutes
                if(clockMins < 10){
                    timeString = timeString + "0" + clockMins + " ";
                }
                else{
                    timeString = timeString + clockMins + " ";
                }
                // set time of day
                if(timeOfDay == 0){
                    timeString = timeString + "am";
                }
                else{
                  timeString = timeString + "pm";
                }

                // Optional bundle stuff
                //bundle.putString("time_string", timeString);
                //message.setData(bundle);

                Log.d("Runnable", "Tracking time @ " + timeString);
                currTimeString = timeString;
                handler.post(clockRunnable);
        }

        private void keepTime(){   
            clockMins = cal.get(Calendar.MINUTE);

            clockHour = cal.get(Calendar.HOUR);
            timeOfDay = cal.get(Calendar.AM_PM);

            checkAlarm(clockHour, clockMins, timeOfDay);        
        }

        private void checkAlarm(int hour, int min, int timeOfDay){
            SharedPreferences alarmPref = getSharedPreferences("alarm_preferences", MODE_PRIVATE);

            int alarmHour = alarmPref.getInt("alarm_hour", -1);
            int alarmMin = alarmPref.getInt("alarm_min", -1);
            int alarmTimeOfDay = alarmPref.getInt("alarm_time_of_day", 0);
            boolean alarmOn = alarmPref.getBoolean("alarm_on", true);

            if(hour == alarmHour && min == alarmMin && timeOfDay == alarmTimeOfDay && alarmOn == true
                    && alarmStartTime != -1){
                startAlarm = true;
            }
            return;
        }
    };
    clockThread.start(); 
}

//TODO: Setup the alarm via the menu that inflates here
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.alarm, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    switch(item.getItemId())
    {
        case R.id.alarm_settings:
            startActivity(new Intent(this, AlarmPopup.class));
            Toast.makeText(this, "Open Up Alarm Dialog", Toast.LENGTH_SHORT).show();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}    


@Override
public void run()
{
    while (clockRunnable != null)
    {
        try
        {
            Thread.sleep(1000);

        } catch (InterruptedException e) { };
        handler.post(clockRunnable);
    }
}


/** PRIVATE METHODS FOR SIMPLIFICATION **/
private void updateUI(){
    if(startAlarm == true){
        //AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarmStartTime = cal.get(Calendar.SECOND);
        currView.setBackgroundColor(Color.RED);
    }
    else if((cal.get(Calendar.SECOND) - alarmStartTime) > DESIRED_ALARM_DURATION){
        alarmStartTime = -1;
        startAlarm = false;
        currView.setBackgroundColor(Color.WHITE);
    }

    clock.setText(currTimeString);
}

显然我在抓住正在发生的事情时遗漏了一些东西,但我不知道是什么。创建后台线程,运行流程,将其传递给处理程序以控制变量,并通过UI更新发送这些变量。我使用http://developer.android.com/guide/faq/commontasks.html来获得理解。

1 个答案:

答案 0 :(得分:0)

不要让活动实现Runnable,而是试试这个:

TimerTask task = new TimerTask() {

        @Override
        public void run() {
            handler.post(clockRunnable);
        }
    };
    Timer timer = new Timer();
    timer.schedule(task, 0, 1000);

即使我会使用不同的方法注册BroadcastReceiver来接收来自系统的tick动作(每秒)。 问候。