Android Handler和Thread在启动时没有运行?

时间:2013-04-05 19:08:59

标签: java android multithreading handler runnable

我正在尝试在我的应用程序的开头创建一个处理程序,所以我可以有两个线程工作1 UI和2我的服务器,我这样做,所以服务器不会阻止UI滞后,并且有用解决我的滞后问题,但无论如何,我正在看这个网站http://crodrigues.com/updating-the-ui-from-a-background-thread-on-android/,该人创建了一个runnable方法,使用run方法,还有一个名为updateGame的方法,当该方法运行时总是调用,现在我已经尝试了他的代码

public class MainActivity extends Activity {

private static final String TAG = gameObject.class.getSimpleName();
//Create a handler to deal with the server
private Handler serverHandler = new Handler();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //Turn off title
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    //Make the application full screen
    getWindow().setFlags(
            WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setContentView( new gamePanel( this ) );
    Log.d( TAG, "View added" );

    //Server method
    new Thread(new Runnable() { onServer( ); } ).start( );
}

final Runnable updateRunnable = new Runnable() {
    public void run() {
        //call the activity method that updates the UI
        updateGame();
    }
};

//Give the positions to the game
public void updateGame()
{
    Log.d(TAG, "Update that game");
}

//Update/run the server
private void onServer()
{
    if( gamePanel.rtnServerState() == true )
    {
        Log.d(TAG, "Start the server");
    }

    serverHandler.post( updateRunnable );
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

public void onDestroy()
{
    Log.d( TAG,  "Destroying... " );
    super.onDestroy();
}

public void onStop()
{
    Log.d( TAG,  "Stopping... " );
    super.onStop();
}
}

我的updateGame只运行一次。任何人都可以看到为什么它不能继续在后台运行的问题吗?

帆布

更新了帖子

public class MainActivity extends Activity {

private static final String TAG = gameObject.class.getSimpleName();
private final Handler serverHandler = new Handler();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //Turn off title
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    //Make the application full screen
    getWindow().setFlags(
            WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setContentView( new gamePanel( this ) );

    TextView textView = new TextView(this);
    textView.setTextSize(40);
    String message = "hello";
    textView.setText(message);

    Log.d( TAG, "View added" );
    //Server method
    new Thread(new Runnable() { 

    @Override
    public void run() { onServer( ); } } ).start( );
}

private void updateServer()
{
    Log.d(TAG, "testing");
}


//Update/run the server
private void onServer()
{
    if( gamePanel.rtnServerState() == true )
    {
        Log.d(TAG, "Start the server");
    }

    serverHandler.post( updateRunnable );
}

//Update/server
final Runnable updateRunnable = new Runnable() {
    public boolean running = true;
    public void run() {
        while(running){
            //call the activity method that updates the UI
            updateServer();
        }
    }
};

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

public void onDestroy()
{
    Log.d( TAG,  "Destroying... " );
    super.onDestroy();
}

public void onStop()
{
    Log.d( TAG,  "Stopping... " );
    super.onStop();
}
}

更新号码2

public class MainActivity extends Activity {

private static final String TAG = gameObject.class.getSimpleName();
private final Handler serverHandler = new Handler();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //Turn off title
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    //Make the application full screen
    getWindow().setFlags(
            WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setContentView( new gamePanel( this ) );

    TextView textView = new TextView(this);
    textView.setTextSize(40);
    String message = "hello";
    textView.setText(message);

    Log.d( TAG, "View added" );
    //Server method
    Runnable server = new Runnable() {
        public boolean running = true;
        public void run() {
            while(running){
                onServer();  // Make sure this blocks in some way
            }
        }
    };
}

private void updateServer()
{
    Log.d(TAG, "testing");
}


//Update/run the server
private void onServer()
{
    if( gamePanel.rtnServerState() == true )
    {
        Log.d(TAG, "Start the server");
    }

    serverHandler.post( updateRunnable );
}

//Update/server
final Runnable updateRunnable = new Runnable() {
    public void run() {
        //call the activity method that updates the UI
        updateServer();
    }
};

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

public void onDestroy()
{
    Log.d( TAG,  "Destroying... " );
    super.onDestroy();
}

public void onStop()
{
    Log.d( TAG,  "Stopping... " );
    super.onStop();
}
}

2 个答案:

答案 0 :(得分:2)

Runnable 对象run方法仅在为响应您的.start()电话创建新线程后调用一次。

通常你会这样做:

final Runnable myRunnable = new Runnable() {
    public boolean running = true;
    public void run() {
        while(running){
            doSomething();
        }
    }
};

但我不确定这是最好的方法。 updateGame()方法将不断被不必要地调用。

相反,将服务器逻辑放在runnable的run()方法中。在那里使用我上面列出的while(running){...}构造,但确保在那里有一些阻塞调用。无论是来自网络套接字,BlockingQueue等,这种方式都不会不必要地循环。


修改

从评论中的讨论。离开

final Runnable updateRunnable = new Runnable() {
    public void run() {
        //call the activity method that updates the UI
        updateGame();
    }
};

原样并改变

new Thread(new Runnable() { onServer( ); } ).start( );

Runnable server = new Runnable() {
    public boolean running = true;
    public void run() {
        while(running){
            onServer();  // Make sure this blocks in some way
        }
    }
}
new Thread(server).start();

答案 1 :(得分:0)

在教程中,UI仅在按钮单击时更新,但您只能在onCreate方法中执行一次。如果您将以@jedwards方式执行此操作,您的UI将在您编写时冻结。不要一直更新UI。尝试使用timersockets更新它。它会更有效,你的UI也不会冻结。

计时器示例

import java.util.Timer;
import java.util.TimerTask;
...

TimerTask task = new TimerTask() {
    @Override
    public void run() {
        // update UI
    }
};
Timer timer = new Timer();
// 1000 - after 1 second run this timer
// 3000 - and do it every 3 second
timer.schedule(task, 1000, 3000);

我不会写套接字示例,因为要写很多东西。我找到了this教程,你可以在这里阅读有关android套接字编程的内容。

BTW当然,您应该只使用套接字或计时器更新您的实体数据,而不是整个UI。