1

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

3 回答 3

6

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 变量 (the edittext) 保存为全局类变量。这样您就可以从 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;
    }


} 
于 2013-07-13T16:04:40.450 回答
1

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

如需更多信息,请阅读 Android 开发者博客中著名的Painless Threading帖子。

于 2013-07-13T16:04:47.690 回答
1

查看处理程序服务

您是否只需要在应用可见时收集数据?您应对这一挑战的方式在很大程度上取决于数据和通信的需求和生命周期。

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

可能会研究一项服务,因为它旨在用于长期运行的作业。

于 2013-07-13T16:20:33.147 回答