什么是权威的,"适当的"在Android应用中执行长时间运行的网络操作的方法?

时间:2017-05-04 15:41:40

标签: android android-asynctask android-service android-thread

我正在开发一个应用程序,它将与UDP服务器通信以获取其数据。显然,这将是一个长期运行的过程(即活动的生命周期),所以我想在后台运行这个过程。当应用程序从UDP服务器获取数据时,我显然会想要操纵数据,以便我可以在应用程序的UI中显示它。

据我所知,有三种方法可以在后台运行长时间运行的流程:

  1. 标准Java线程
  2. 的AsyncTask
  3. 服务(有界)
  4. 对于标准的Java线程,通过我在互联网上的搜索,我听到很多关于如何在Android中创建自己的线程不是一个好主意的抱怨。我之前尝试过这条路线并且确实有效,但是为了在应用程序的UI中使用线程的接收数据,它还需要相当多的操作。

    对于AsyncTask,Android文档本身说:

      

    理想情况下,AsyncTasks应该用于短操作(最多几秒钟。)

    这对我来说并不好,因为我需要这个线程在整个活动期间运行。

    最后,有绑定的服务。这似乎完全符合我的需求。再次,从Android文档:

      

    服务是一种可以在后台执行长时间运行的应用程序组件,它不提供用户界面。另一个应用程序组件可以启动服务,即使用户切换到另一个应用程序,它也会继续在后台运行。此外,组件可以绑定到服务以与其交互,甚至可以执行进程间通信(IPC)。

    读完这一点后,我继续沿着Android服务路径前进。事情进展顺利,直到我试图运行我的应用程序。

    首先,这是我的服务:

    Listener.java

    public class Listener extends Service {
    
        private boolean keepWorking = true;
        private int localPort;
        private final IBinder iBinder = new LocalBinder();
    
        public class LocalBinder extends Binder {
            Listener getService(){
                return Listener.this;
            }
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return iBinder;
        }
    
        public void listenToServer(){
            try {
                byte[] buffer = new byte[16 * 1024];
                DatagramPacket recvPacket = new DatagramPacket(buffer, buffer.length);
                DatagramSocket server = new DatagramSocket(0);
                server.setSoTimeout(1000);
                localPort = server.getLocalPort();
    
                while (keepWorking) {
                    try {
                        server.receive(recvPacket);
                        byte[] data = new byte[recvPacket.getLength()];
                        System.arraycopy(recvPacket.getData(), 0, data, 0, data.length);
                        // Do stuff with the data ...
                    } catch ( IOException ioe) {
                        // something here
                    }
                }
            } catch (SocketException se) {
                // something here
            }
        }
    
        public int getPort() {
            return this.localPort;
        }
    
        public void stopWorking() {
            this.keepWorking = false;
        }
    }
    

    并且,我的 MainActivity.java 绑定到此服务:

    public class MainActivity extends AppCompatActivity {
    
        Listener myListener;
        boolean isBound = false;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            Intent intent = new Intent(this, Listener.class);
            startService(intent);
            bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            if(isBound){
                unbindService(serviceConnection);
                isBound = false;
            }
        }
    
        private ServiceConnection serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Listener.LocalBinder localBinder = (Listener.LocalBinder) service;
                myListener = localBinder.getService();
                myListener.listenToServer();
                isBound = true;
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                isBound = false;
            }
        };
    }
    

    我很快发现,即使我是从服务中执行此操作,但显然仍然仍然从主线程运行,因为我收到此错误:

    android.os.NetworkOnMainThreadException
    

    从我的 Listener.java 中读取server.receive(recvPacket);的行。

    在挖掘之后,我发现无论如何我可能需要一个线程或AsyncTask来处理它。

    所以,我的问题是:什么是权威的,"正确的"如何在Android应用程序中执行长时间运行的网络操作?

    为什么Android会让它变得如此困难,那就是真正的"面包和黄油" Android应用程序?我知道我不能成为第一个想要这样做的人。

    感谢您的帮助。

0 个答案:

没有答案