在java Android中不断更新GUI

时间:2013-07-13 15:54:23

标签: java android user-interface

我是Eclipse for Android平台的新java程序员。 我正在开发一个Android应用程序,它将通过wifi接口接收多播数据,并在TextView中显示相同的内容。数据将每1秒更新一次。

我的代码如下。但我在更新GUI时面临问题。在此代码中,网络接收和gui在相同的线程中完成,即主线程,这就是我的应用程序挂起的原因。

我曾尝试使用AsynchTask,但无法成功,因为我不知道如何使用它。

package com.example.cdttiming;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.Menu;
import android.widget.EditText;



public class MainActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        EditText Seconds;
        Seconds =(EditText)findViewById(R.id.Seconds);

        WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE);
        WifiManager.MulticastLock multicastLock = wm.createMulticastLock("mydebuginfo");
        multicastLock.setReferenceCounted(true);
        multicastLock.acquire();

        InetAddress ia = null;
        byte[] buffer = new byte[65535];
        MulticastSocket ms = null;
        int port = 4321;
        try
        {
            ia = InetAddress.getByName("226.1.1.1");
            DatagramPacket dp = new DatagramPacket(buffer, buffer.length,ia,port);
            ms = new MulticastSocket(port);
            ms.setReuseAddress(true);
            ms.joinGroup(ia);

            while (true)
            {
                ms.receive(dp);
                String s = new String(dp.getData(),0,dp.getLength());
                Seconds.setText(s);
            }
            }
        catch (UnknownHostException e)
        {
            Seconds.setText(e.getMessage());
        }
        catch (IOException e)
        {
            Seconds.setText(e.getMessage());
        }
    }

    @Override
     public boolean onCreateOptionsMenu(Menu menu)
    {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

任何人都可以告诉我如何使用上面的代码,以便我可以每秒接收数据并在TextView中显示它吗?

提前感谢你们

4 个答案:

答案 0 :(得分:5)

AsyncTask并不适用于您的用例。如果后台任务需要连续运行,那么最好只需启动一个新线程。在线程中使用处理程序将值传递给UI。在处理程序的回调方法中,您可以更新gui。

有关处理程序的更多信息:

  1. http://mobileorchard.com/android-app-developmentthreading-part-1-handlers/

  2. http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html

  3. http://developer.android.com/reference/android/os/Handler.html

  4. 或谷歌提供良好的例子来实现这一目标。

    编辑:

    好的,你需要做的是启动一个新线程,在run方法中放入从套接字读取的部分。 您可以像在内部类中一样创建线程,例如:

    class SocketThread extends Thread {
        private final Handler mHandler;
        private final WifiManager mWifiManager;
        SocketThread(Handler handler, WifiManager wifiManager) {
            mHandler = handler;
        }
        @override public void run() {
            // socket code goes here
            // whenever you receive a part that should update the ui,
            // do something like:
            final String s = new String(dp.getData(),0,dp.getLength());
            mHandler.post(new Runnable() {
                @override
                public void run() {
                    update(s);
                }
            });
        }
    }
    

    然后在你的onCreate()中创建一个处理程序和该线程的一个实例并启动它。

    ...
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    EditText Seconds;
    Seconds =(EditText)findViewById(R.id.Seconds);
    
    WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE);
    Handler handler = new Handler();
    SocketThread thread = new SocketThread(handler, wm);
    thread.start();
    ...
    

    还在您的活动中定义方法更新。在这里,您将收到要设置的文本。此方法如下所示:

    public void update(String s) {
        Seconds.setText(s);
    }
    

    我建议你将seconds变量(edittext)保存为全局类变量。这样,您可以从更新方法写入它,而无需先findById

    我编辑了你的代码,它可能与wifi代码有关。我不熟悉框架的这一部分。但我可以想象它与WifiManager有关并且与它有关。如果这不起作用,设置一个断点并逐步执行它,你会看到它停止做任何事情。

    package com.example.timing;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.InetAddress;
    import java.net.MulticastSocket;
    import java.net.UnknownHostException;
    
    import android.app.Activity;
    import android.content.Context;
    import android.net.wifi.WifiManager;
    import android.os.Bundle;
    import android.os.Handler;
    import android.view.Menu;
    import android.widget.Button;
    import android.widget.EditText;
    
    public class MainActivity extends Activity {
        EditText Seconds;   
        String s;
        Button button;
        byte[] buffer = new byte[65535];
        InetAddress ia = null;
        int port = 4321;     
        DatagramPacket dp = new DatagramPacket(buffer, buffer.length,ia,port);
        MulticastSocket ms = null;
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);     
            Seconds = (EditText) findViewById(R.id.et_time);    
            WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE); 
    
            Handler handler = new Handler();
            SocketThread thread = new SocketThread(handler, wm);
            thread.start();
        }
    
    
    
        class SocketThread extends Thread  {
            private final Handler mHandler;
    
            SocketThread(Handler handler, WifiManager wifiManager) {
                mHandler = handler;
            }
            @Override 
            public void run() {
                // socket code goes here            
                try {     
                    wm.setWifiEnabled(true);        
                    WifiManager.MulticastLock multicastLock = wm.createMulticastLock("multicastLock");
                    multicastLock.setReferenceCounted(true);        
                    multicastLock.acquire();            
    
                    ia = InetAddress.getByName("226.1.1.1");         
                    ms.setReuseAddress(true);
                    ms.joinGroup(ia);
    
                    while(true) {
                    ms.receive(dp);     
                        s = new String(dp.getData(),0,dp.getLength());
                        update(s);
                    }
                } catch (UnknownHostException e) {
                    update(e.getMessage());
                } catch (IOException e) {
                    update(e.getMessage());
                }       
            }
        }
    
    
        public void update(String s)
        {
            Seconds.setText(s);
        }   
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu)
        {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
    
    } 
    

答案 1 :(得分:1)

您不应该使用AsyncTask进行更持久的活动 - 请使用简单的Thread和Handler。在线程中,您执行WI-FI的操作(基本上是您的while(true)循环),并且每当您想要更新UI时,都会将消息传递给Handler并在UI线程中处理消息。

有关详细信息,请阅读Android开发者博客中着名的Painless Threading帖子。

答案 2 :(得分:1)

浏览HandlersServices

您只需在应用可见时收集数据吗?您应对这一挑战的方式非常依赖于数据和通信的需求和生命周期。

AsyncTask通常用于在单独的线程上执行一个off作业,然后在完成时通知主线程。

可能会查看服务,因为它适用于长期工作。

答案 3 :(得分:0)

您也可以学习Firebase for android.