【问题标题】:Looping a Thread循环线程
【发布时间】:2015-03-01 17:09:19
【问题描述】:

在我的 android 应用程序中,我想连续读取传入数据(使用 Telnet 协议)。我能够读取一行(然后应用程序在空闲状态下运行),我想知道如何创建一个简单的无限主循环。

我认为在这一行周围放一个循环是有意义的:

telnetThread.start();

我已经尝试实现一个looper,但没有任何成功。

这是我的代码:

package com.example.clienttel;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;

import org.apache.commons.net.telnet.TelnetClient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class MainActivity extends ActionBarActivity {
    // Variables
    public final String ADDRESS = "194.66.82.11";
    public final int PORT = 50100;
    public String NMEA = null;
    public final String TAG = "TestApp";
    public boolean first = true;
    public MyTelnetClass mtc;
    public Thread telnetThread;

    // Handler in mainthread
    Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            String dataString = "";
            Bundle bundle = msg.getData();

            Log.d("handleMessage", bundle.toString());
            if (bundle.containsKey("outgoingString")) {
                dataString = bundle.getString("outgoingString");
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        createThread();
    }

    private void createThread() {
        final Runnable runnable = new Runnable() {
            public void run() {
                try {
                    mtc = new MyTelnetClass();
                    mtc.mhandler = handler;
                    mtc.run();

                    Bundle b = new Bundle();
                    b.putString("TCPThread", "visible");
                    Message m = handler.obtainMessage();
                    m.setData(b);
                    handler.sendMessage(m);
                } catch (Exception e) {
                    Log.e("createTCPThread", "exception: " + e.getMessage());
                    Bundle b = new Bundle();
                    b.putString("TCPThread", "unvisible");
                    Message m = handler.obtainMessage();
                    m.setData(b);
                    handler.sendMessage(m);
                }
            }
        };
        // create the thread needed and run it, LOOP HERE?
        telnetThread = new Thread(runnable);
        telnetThread.start();
    }

    // catch NMEA-sentences and send them using mhandler
    class MyTelnetClass {
        public Handler mhandler = null;

        public void run() {
            TelnetClient telnet = new TelnetClient();
            Log.i(TAG, "telnetThread active");
            if (first) {
                // Connect To Server in 1st Iteration
                try {
                    telnet.connect(ADDRESS, PORT);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                first = false;
            }

            // Process NMEA-sentences
            InputStream inStream = telnet.getInputStream();
            BufferedReader r = new BufferedReader(new InputStreamReader(inStream));

            try {
                NMEA = r.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }

            // Handler in MyTelnetClass to send back
            Bundle b = new Bundle();
            b.putString("outgoingString", NMEA);

            Message m = mhandler.obtainMessage();
            m.setData(b);
            mhandler.sendMessage(m);
        }
    }
}

什么是处理这个问题的有效方法?

编辑:

我把 looper 放在了 run() 的“周围”,但它只执行一次(我不确定循环是否可以这样工作):

public void run() {
                try {
                    Looper.prepare(); // HERE...

                    Log.d(TAG,"executing run");
                    mtc = new MyTelnetClass();
                    mtc.mhandler = handler;
                    mtc.run();

                    Bundle b = new Bundle();
                    b.putString("TCPThread", "visible");
                    Message m = handler.obtainMessage();
                    m.setData(b);
                    handler.sendMessage(m);

                    Looper.loop(); // ...AND HERE
                } catch (Exception e) {
                    Log.e("createTCPThread", "exception: " + e.getMessage());
                    Bundle b = new Bundle();
                    b.putString("TCPThread", "unvisible");
                    Message m = handler.obtainMessage();
                    m.setData(b);
                    handler.sendMessage(m);
                }
            }

【问题讨论】:

  • 弯针并不是你想象的那样。可能你想要的是在你的线程中像 while() 构造一样简单的东西,但如果它不与 Activity 紧密联系,你可能希望在服务中使用该线程。
  • 我花了一段时间,但它让我不停createTCPThread﹕ exception: null
  • 你的 catch 需要做一个 e.printStackTrace()。然后检查完​​整的异常并修复它。
  • Error is here (NullpointerException) : BufferedReader r = new BufferedReader(new InputStreamReader(inStream)); 我已经遇到了这个问题,我不知道如何解决它...可能与我正在使用的 Telnet 库有关
  • 可以用简单的if (inStream != null) 解决问题。现在的问题是我每次都得到相同的数据......要处理那个......

标签: java android loops main


【解决方案1】:

你已经创建了一个线程,这是你的开始,但它会运行一次。 如果您希望他循环运行,则需要放置循环。 循环需要在run() 方法中,从开始到结束,或者尽可能多地使用它。

如果你在你推荐的地方写了一个循环,那将是浪费时间(/内存)并且没有效果,它会一遍又一遍地创建相同的线程。 如果你在telnetThread.start(); 所在的位置执行此操作,则会导致大量线程,并且它们都将在大约同一时间运行。

如果您在 run() 函数中执行此操作,它将无限次运行(除非您有条件)并且仅在循环的最后一次运行结束后运行。

【讨论】:

  • 我按照你的建议做了(见上面的编辑),但它只在 logcat 中显示"executing run" 一次,这意味着循环挂起或卡在某个地方。有什么想法吗?
  • s 看起来 run 方法有问题。您可以尝试添加更多日志以查看卡在哪里吗?o
  • an 会建议使用简单的 while 循环来避免问题。不过,请确保没有函数像 socket 那样阻塞线程。这可能会导致这个问题
  • 没问题 :) 只是想知道,你为什么从第一次开始就用 looper?
【解决方案2】:

试试下面的代码:

   {
                new Thread () {
                    public void run() {
                        Message msg = Message.obtain();
                        msg.what=1;         
                        try {
                            openTelnetConnection(url, mmsgH); 
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();                        }                                                                                       
                            }
                }.start();         
            }
        private void openTelnetConnection(String urlStr, Handler mhandler) throws IOException {
            ProtocolConnection protConn = null;
            String line = null;
            try {

                // Get your CONNECTION
                BufferedReader is =
                        new BufferedReader(new InputStreamReader(protConn.getInputStream()));                   

                while ((line = is.readLine( )) != null) {

                        Message msg = Message.obtain();
                        msg.what=1;  
                        msg.obj=line;                       
                        mhandler.sendMessage(msg);
                }               
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch( SocketTimeoutException e){
                e.printStackTrace();
            } catch (IOException e) {
                Log.d(TAG, "IOERR " +e);
                e.printStackTrace();
                Message msg = Message.obtain();
                    msg.what=2;
                    BufferedInputStream in = new BufferedInputStream(httpConn.getErrorStream());            
                    line =new String(readStream(in));
                    msg.obj=line;
                    mhandler.sendMessage(msg);                
            }
            finally {protConn.disconnect();}
        }

【讨论】:

    【解决方案3】:

    正如@ChrisStratton 和@amitfarag 所说,一个简单的while()-loop 完全符合我的要求。在我的情况下不需要循环器:

    while (true) {
                        try {
                            mtc = new MyTelnetClass();
                            mtc.mhandler = handler;
                            mtc.run();
    
                            Bundle b = new Bundle();
                            b.putString("TCPThread", "visible");
                            Message m = handler.obtainMessage();
                            m.setData(b);
                            handler.sendMessage(m);
                        } catch (Exception e) {
                            Log.e("createTCPThread", "exception: " + e.getMessage());
                            Bundle b = new Bundle();
                            b.putString("TCPThread", "unvisible");
                            Message m = handler.obtainMessage();
                            m.setData(b);
                            handler.sendMessage(m);
                            e.printStackTrace();
                        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-03
      • 2015-06-14
      • 2014-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多