繁体   English   中英

持续更新Java Android中的GUI

[英]Continuously updating GUI in java Android

我是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中?

预先谢谢大家

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

或谷歌的好例子,以使这一点。

编辑:

好的,您需要做的是启动一个新线程,然后在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变量( edittextedittext为全局类变量。 这样,您可以从update方法写入它,而不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;
    }


} 

您不应将AsyncTask用于更长时间的活动-而是使用简单的线程和处理程序。 在该线程中,您进行WI-FI处理(基本上是while(true)循环),并且每当要更新UI时,就将消息传递给Handler并在UI线程中处理该消息。

有关更多信息,请阅读Android开发者博客中著名的无痛线程文章。

浏览处理程序服务

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

AsyncTask通常用于在单独的线程上完成一次工作,然后在完成后通知主线程。

可能会针对长期运行的工作调查服务。

您也可以学习适用于Android的Firebase。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM