2013-06-09 5 views
0

Я пишу простое приложение для Android, чтобы продемонстрировать методы wait() и notify(). Приложение содержит 1 кнопку и 1 textView, textView покажет таймер, и кнопка отобразит диалог, содержащий 2 кнопки. теперь то, что я хочу сделать, - это когда я нажимаю кнопку диалога, паузу времени и всякий раз, когда я возвращаюсь, нажимая кнопку возобновления в диалоговом окне, время продолжается и так далее.это право для wait() и notify() и как исправить

Вот мой код:

public class MainActivity extends Activity implements OnClickListener{ 

Timer t; 
int count = 0; 

Button b; 
TextView tv; 

Thread thread; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    b = (Button) findViewById(R.id.button1); 
    tv = (TextView) findViewById(R.id.textView1); 

    t = new Timer(); 
    t.scheduleAtFixedRate(new TimerTask() { 

     @Override 
     public void run() { 
      // TODO Auto-generated method stub 
      runOnUiThread(new Runnable() { 
       public void run() { 
       tv.setText(String.valueOf(count)); 
       count++; 
       } 
      }); 
     } 
    }, 1000, 1000); 

    b.setOnClickListener(this); 


} 


@Override 
public void onClick(View v) { 
    // TODO Auto-generated method stub 

    synchronized (MainActivity.this) 
    { 
     try { 
      wait(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

    final Dialog d = new Dialog(this); 
    d.setTitle("Pause Menu"); 
    d.setContentView(R.layout.pausemenu); 
    Button b1 = (Button) d.findViewById(R.id.Resume); 
    Button b2 = (Button) d.findViewById(R.id.Main); 

    b1.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      // TODO Auto-generated method stub 
      d.cancel(); 
      thread = new Thread() 
      { 
       public void run() 
       { 
        synchronized (MainActivity.this) { 
         try { 
          wait(1000); 

         }catch (Exception e) { 
          // TODO: handle exception 
         } 

         notify(); 
        } 
       } 
      }; 
     } 
    }); 

    b2.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      // TODO Auto-generated method stub 
      d.cancel(); 
     } 
    }); 
    d.show(); 

} 
} 

и вот LogCat:

06-09 08:07:55.066: E/AndroidRuntime(635): FATAL EXCEPTION: main 
06-09 08:14:43.946: E/AndroidRuntime(664): FATAL EXCEPTION: main 
06-09 08:14:43.946: E/AndroidRuntime(664): java.lang.NullPointerException 
06-09 08:14:43.946: E/AndroidRuntime(664): 
at com.example.timerwithnotify.MainActivity.onClick(MainActivity.java:58) 
06-09 08:14:43.946: E/AndroidRuntime(664):  
at android.view.View.performClick(View.java:2408) 
06-09 08:14:43.946: E/AndroidRuntime(664): 
at android.view.View$PerformClick.run(View.java:8816) 
06-09 08:14:43.946: E/AndroidRuntime(664): 
at android.os.Handler.handleCallback(Handler.java:587) 
06-09 08:14:43.946: E/AndroidRuntime(664):  
at android.os.Handler.dispatchMessage(Handler.java:92) 
06-09 08:14:43.946: E/AndroidRuntime(664): at android.os.Looper.loop(Looper.java:123) 
06-09 08:14:43.946: E/AndroidRuntime(664): 
at android.app.ActivityThread.main(ActivityThread.java:4627) 
06-09 08:14:43.946: E/AndroidRuntime(664): 
at java.lang.reflect.Method.invokeNative(Native Method) 
06-09 08:14:43.946: E/AndroidRuntime(664): 
at java.lang.reflect.Method.invoke(Method.java:521) 
06-09 08:14:43.946: E/AndroidRuntime(664): 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
06-09 08:14:43.946: E/AndroidRuntime(664): 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 

пожалуйста, покажите мне в коде, как это исправить, им еще нуб: D. Спасибо за ваше время и внимание.

+0

final Диалог d = новый Диалог (это); должен быть окончательным Диалог d = новый диалог (MainActivity.this); – Raghunandan

+0

Также, если вы реализуете Thread или HandlerThread, убедитесь, что поток пользовательского интерфейса не блокируется в ожидании завершения рабочего потока - не вызывайте Thread.wait() или Thread.sleep(). Проверьте это http://developer.android.com/training/articles/perf-anr.html – Raghunandan

+0

та же проблема :( – Coderji

ответ

1

Не уверен, что вы пытаетесь сделать. Вы можете использовать приведенное ниже для справки.

Если вы реализуете Thread or HandlerThread, убедитесь, что поток пользовательского интерфейса не блокируется во время ожидания рабочего потока - не вызывайте Thread.wait() или Thread.sleep().

Проверить это developer.android.com/training/articles/perf-anr.html

Вы не должны блокировать ваш основной поток пользовательского интерфейса. Вместо таймера вы можете использовать «Handler»

Вы можете запустить и остановить таймер при нажатии кнопки. Вы можете перенести свой таймер со значением счета. Вам необходимо позаботиться об изменении ориентации, поскольку деятельность разрушается и воссоздается. Значение счетчика будет повторно инициализировано.

MainActivity.java

public class MainActivity extends Activity implements OnClickListener{ 

Timer t; 
int count = 0; 
boolean isDone = true; 
Button b; 
TextView tv; 

Thread thread; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    b = (Button) findViewById(R.id.button1); 
    tv = (TextView) findViewById(R.id.textView1); 

    t = new Timer(); 
    t.scheduleAtFixedRate(new TimerTask() { 

     @Override 
     public void run() { 
      // TODO Auto-generated method stub 
      runOnUiThread(new Runnable() { 
       public void run() { 
       tv.setText(String.valueOf(count)); 
       if(isDone) 
       count++; 

       } 
      }); 
     } 
    }, 1000, 1000); 

    b.setOnClickListener(this); 


} 


@Override 
public void onClick(View v) { 
    // TODO Auto-generated method stu 

    final Dialog d = new Dialog(MainActivity.this); 
    d.setTitle("Pause Menu"); 
    d.setContentView(R.layout.pausemenu); 
    Button b1 = (Button) d.findViewById(R.id.button1); 
    Button b2 = (Button) d.findViewById(R.id.button2); 

    b1.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      // TODO Auto-generated method stub 
      t.cancel(); 
      d.dismiss(); 

     } 
    }); 

    b2.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      // TODO Auto-generated method stub 
      if(isDone) 
      { 
       t.cancel(); 
       isDone=false; 
      } 
      t = new Timer(); 
      t.scheduleAtFixedRate(new TimerTask() { 

        @Override 
        public void run() { 
         // TODO Auto-generated method stub 
         runOnUiThread(new Runnable() { 
          public void run() { 
          tv.setText(String.valueOf(count)); 
          count++; 
          } 
         }); 
        } 
       }, 1000, 1000); 
      d.dismiss(); 
     } 
    }); 
    d.show(); 

} 
} 

main.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <TextView 
     android:id="@+id/textView1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerHorizontal="true" 
     android:layout_centerVertical="true" 
     android:textSize="20sp" 
     android:text="TextView" /> 

    <Button 
     android:id="@+id/button1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_alignRight="@+id/textView1" 
     android:layout_marginBottom="21dp" 
     android:text="Button" /> 

</RelativeLayout> 

pausemenu.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <Button 
     android:id="@+id/button1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_alignParentLeft="true" 
     android:layout_marginBottom="118dp" 
     android:layout_marginLeft="51dp" 
     android:text="Stop" /> 

    <Button 
     android:id="@+id/button2" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignBaseline="@+id/button1" 
     android:layout_alignBottom="@+id/button1" 
     android:layout_marginLeft="32dp" 
     android:layout_toRightOf="@+id/button1" 
     android:text="Start" /> 

</RelativeLayout> 

Edit:

Использование Handler

Handler m_handler; 
    Runnable m_handlerTask ; 
    m_handlerTask = new Runnable() 
{ 
    @Override 
    public void run() { 
     if(isDone) 
     { 
      tv.setText(""+count); 
      count++; 
      m_handler.postDelayed(m_handlerTask, 1000); 
     } 
     // m_handler.removeCallbacks(m_handlerTask); 
    } 
}; 
m_handlerTask.run();  

Вы должны остановить таймер и отменить обработчик, когда это не требуется.

Вызов t.cancel(), если ваш с помощью таймера и использовать m_handler.removeCallbacks(m_handlerTask), чтобы остановить обработчику

0

В коде

public void onClick(View v) { 
     synchronized (MainActivity.this) 
     { 
      try { 
       wait(); 

Никогда не подвешивать нить Android GUI с wait заявления. Приостановка этой нити заставит весь графический интерфейс перестать отвечать на ваши входы, а операционная система Android может закрыть программу автоматически после обнаружения ситуации.

Кроме того, поток запускается только после вызова метода запуска, который вы никогда не делаете. Наконец, вы вызываете wait и notify на сам поток (внутренний класс), но ни один код в другом месте не уведомляет об этом, чтобы поток постоянно останавливался.Конечно, это, безусловно, менее проблематично, если вы даже не начинаете его.

Я бы предложил вам прочитать хороший учебник по многопоточности.