当前位置: 首页 > 知识库问答 >
问题:

为什么当我在一个单独的线程上运行类时(实现Runnable)会得到“Android.os.NetworkOnMainThreadException”?

贝镜
2023-03-14

在我的应用程序中,我有一个队列,其中包含数据库中应该发送到服务器的项目。由于我希望这个队列被持续监视,并且由于这个任务包括网络通信,所以我创建了一个实现Runnable的类,我将其称为QueueWorkerThread。但是出于某种原因,我仍然得到了“Android.os.NetworkonMainThreadException”,我不明白为什么?我尝试在SO上搜索类似的问题,但任何更接近的都是使用AsyncTask,因为这个类显然会在API级别30中变得低级,所以我不想使用它(我希望这个应用程序能工作很长时间)。我的Runnable是不是以某种方式在主线程上运行了一些东西?这可能吗?

以下是我的QueueWorker线程的代码:

public class QueueWorkerThread implements Runnable{
private final static String TAG = "QueueWorkerThread";
private AtomicBoolean alive = new AtomicBoolean(true);
private Context mContext;
private FragmentRefreshInterface mFragmentRefreshInterface;
private NetworkStatusInterface mNetworkStatusInterface;

public QueueWorkerThread(Context context, FragmentRefreshInterface fragmentRefreshInterface, NetworkStatusInterface networkStatusInterface) {
    mContext = context;
    mFragmentRefreshInterface = fragmentRefreshInterface;
    mNetworkStatusInterface = networkStatusInterface;
    Log.d(TAG," Thread Started");
}

public void quit(){
    alive.set(false);
}

public void makeReady(){
    alive.set(true);
}

@Override
public void run() {
    SQLiteDatabase database = SQLiteHelper.getSingleton(mContext).getWritableDatabase();
    ServerCommunicationHelper communicationHelper = new ServerCommunicationHelper(mFragmentRefreshInterface,mNetworkStatusInterface);
    while (alive.get()){
        TracerQueueVO tracerQueueVO = SQLiteHelper.getSingleton(mContext).getNextQueueVOFromDatabase(database);

        if(tracerQueueVO.getTracerId()!=null){
            int result = communicationHelper.uploadQueueVO(tracerQueueVO, mContext);
            if(result == ServerCommunicationHelper.UPLOAD_OK){
                SQLiteHelper.getSingleton(mContext).removeQueueVOFromDatabase(database,tracerQueueVO);
            }else{
                SQLiteHelper.getSingleton(mContext).updateQueueVOInDatabase(database,tracerQueueVO);
            }
        }
        try {
            sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
private void startQueueWorkerThread(){
    if (mQueueWorkerThread == null){
        mQueueWorkerThread = new QueueWorkerThread(mContext,this, this);
        new Thread(mQueueWorkerThread).start();
    } else {
        mQueueWorkerThread.makeReady();
        mQueueWorkerThread.run();
    }
}
public int uploadQueueVO(ItemQueueVO queueVO, Context context){
int result = 0;
try {
    String json = queueVO.getData();
    byte[] base64 = Base64.encode(json.getBytes(),0);
    final OkHttpClient CLIENT = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .post(RequestBody.create(MediaType.parse("text/plain; charset=utf8"),base64))
                .build();
        Response response = CLIENT.newCall(request).execute();

        if (response.isSuccessful()){
            result = UPLOAD_OK;
        }else{
            result = UPLOAD_FAILED;
        }

    } catch (Exception e) {
        e.printStackTrace();
        result = UPLOAD_FAILED;
    }
    return result;

这是堆栈跟踪:

W/System.err: android.os.NetworkOnMainThreadException
    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1565)
W/System.err:     at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:389)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
W/System.err:     at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
    at java.net.Socket.connect(Socket.java:621)
    at okhttp3.internal.platform.AndroidPlatform.connectSocket(AndroidPlatform.java:73)
W/System.err:     at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:245)
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:165)
W/System.err:     at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
    at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
W/System.err:     at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200)
W/System.err:     at okhttp3.RealCall.execute(RealCall.java:77)
    at com.xxxxxx.xx.network.ServerCommunicationHelper.uploadQueueVO(ServerCommunicationHelper.java:136)
W/System.err:     at com.xxxxxx.xx.queue.QueueWorkerThread.run(QueueWorkerThread.java:49)
    at com.xxxxxx.xx.MainActivity.startQueueWorkerThread(MainActivity.java:1193)
    at com.xxxxxx.xx.MainActivity.onResume(MainActivity.java:373)
    at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1454)
    at android.app.Activity.performResume(Activity.java:8105)
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4529)
W/System.err:     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4572)
    at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
    at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2220)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:237)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:8016)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)

共有1个答案

张积厚
2023-03-14

else部分,您直接调用run方法,这些方法将在邮件线程上执行网络调用,因此出现异常

// this method is being called in onResume so
// second time, mQueueWorkerThread.run will be executed on main thread
private void startQueueWorkerThread(){
    if (mQueueWorkerThread == null){
        mQueueWorkerThread = new QueueWorkerThread(mContext,this, this);
        new Thread(mQueueWorkerThread).start();
    } else {
        mQueueWorkerThread.makeReady();
        mQueueWorkerThread.run(); // it will cause the exception
        // new Thread(mQueueWorkerThread).start(); should use this
    }
}
 类似资料:
  • 我有一个异步方法,它调用另一个异步方法,但是,我希望它在单独的线程上并行运行: 事实上,这就是我正在努力做的。为什么我会收到编译器警告?task.run的语法不正确吗?

  • Java线程的run()方法在线程启动时由该线程上的JVM调用。要让线程做一些事情,您可以创建thread的子类并重写它的run()方法,或者(最好)您可以为线程的构造函数提供一个Runnable。那很好。 当时我正在创建Thread的子类并重写run,我意识到我不能像预期的那样使方法受到保护,因为Thread.run()是公共的。然后我意识到为什么:它必须是公共的,因为Thread实现了Runn

  • 我还尝试了,,JMeter获得了多达8000个示例,最大时间12000ms(超时30s),并给出了错误。在拒绝之前,它至少应该排队10,000个连接。

  • AMQ6235E:缺少目录“H:”。 我无法找到解决这个问题的方法,它正在连接队列,它显示了这个错误。我不能公开我运行的代码,但我可以解释节点脚本将做什么,首先尝试连接队列管理器,然后尝试通道名,主机名,端口名,这里问题是当它需要建立连接而不是得到上面的错误

  • 这是我的整个测试课程: 有3个单元测试,它们在单独运行时都通过了,但当我运行整个测试类时,我的第2个和第3个测试失败,错误如下: 我已经想尽一切办法来解决这个问题: 我将测试实例化下的类移动到@Before函数中 我尝试创建@After函数并调用Mockito。重置我的模拟 我应该提到的是,我正在使用nhaarman。mockitokotlin2库和argumentCaptor。 关于为什么这些测

  • 我有一个使用servlet公开REST API的Camel应用程序。我用SpringBoot和Camel一起。在构建WAR之后,我可以使用java-jar运行它,它工作得很好。现在,当我将相同的WAR部署到Tomcat/WebApps中时,日志中会出现以下错误: 这是我的web.xml