【问题标题】:Read web service response from Service ends with NetworkOnMainThreadException从 Service 读取 Web 服务响应以 NetworkOnMainThreadException 结尾
【发布时间】:2017-09-07 21:12:43
【问题描述】:

我有一个连接到 Web 服务并读取最新数据的类。它是:

public class LatestProductsReader extends Thread {
private String mResponse = "";

class SoapLatestProduct extends SoapConnector {
    public SoapLatestProduct(String web_service_address) {
        super("GetLatestParts", web_service_address);
    }
}

public void run() {
    String url = "my_web_service_address";

    try {

        SoapLatestProduct latestProduct = new SoapLatestProduct(url);
        mResponse = latestProduct.call();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}
public String getResponse() {
    return mResponse;
}
}

我希望这个类的实例每 10 分钟从服务中调用一次。我写了下面的代码,但总是以 NetworkOnMainThreadException 结束。有什么问题?

public class SynchronizerService extends Service implements {
// .
// .
// .

private Timer mTimer=null; // timer handling
private Handler mHandler = new Handler();

@Nullable
@Override
public IBinder onBind(Intent intent) {
   return null;
}

@Override
public int onStartCommand(Intent intent, int flag, int startId) {
   Runnable runnable = new Runnable() {
       public void run() {
           mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(),
                   0,
           TICK_INTERVAL);
       }
   };

   Thread t = new Thread(runnable);
   t.run();
   
   return START_STICKY;
}

@Override
public void onCreate() {
   // cancel if service is  already existed
   if(mTimer!=null)
       mTimer.cancel();
   else
       mTimer=new Timer(); // recreate new timer
}

@Override
public void onDestroy() {
   Toast.makeText(this, "In Destroy", Toast.LENGTH_SHORT).show();//display toast when method called
   mTimer.cancel();//cancel the timer
}


private class TimeDisplayTimerTask extends TimerTask {
    @Override
    public void run() {
        // run on another thread
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    // display toast at every tick
                    LatestProductsReader PartCallert = new LatestProductsReader();
                    PartCallert.run();
                    PartCallert.join();
                    PartCallert.start();

                    while(PartCallert.getResponse() == null || PartCallert.getResponse().isEmpty()){
                        Thread.sleep(10);
                   }

                    String res = PartCallert.getResponse();
                    Toast.makeText(getApplicationContext(), res , Toast.LENGTH_SHORT).show();
                }
               catch (Exception ex){
                   ex.printStackTrace();
               }
           }
       });
   }
 }
}

【问题讨论】:

    标签: android multithreading exception networking service


    【解决方案1】:

    当应用程序尝试在其主线程上执行网络操作时会引发此异常。在 AsyncTask 中运行您的代码。

    【讨论】:

    • 我已经知道异常的原因,但是如何修复 LatestProductReader 类或服务以防止异常?
    • 将 LatestProductReader 的基类更改为 AsyncTask 并没有解决问题
    • 可以看到Service类中AsyncTask的例子:stackoverflow.com/questions/22043652/…
    【解决方案2】:

    我将此答案发布给未来的读者。虽然可以用不同的方法解决,但这个解决了我的问题。我从 AsyncTask 继承了每个 Reader 类,并为每个类创建了一个观察者接口来通知用户类 (SyncronizerService)。示例类如下:

    public class LatestCustomersReader extends AsyncTask<Void, Void, String> {
    private SoapLatestCustomer reader = null;
    private OnCustomerChangeListener mListener;
    
    public interface OnCustomerChangeListener {
        void customerAdded(Customer customer);
    }
    
    public class SoapLatestCustomer extends SoapConnector {
        public SoapLatestCustomer(String web_service_address) {
            super("GetLatestCustomers", web_service_address);
        }
    }
    
    public LatestCustomersReader(OnCustomerChangeListener listener){
        mListener = listener;
    }
    
    @Override
    protected String doInBackground(Void... params){
        // Do my stuff
        SoapLatestCustomer reader = new SoapLatestCustomer(url);
        String response = reader.call();
    
        return response
    }
    
    // other AsynTask methods
    }
    

    和用户类:

    public class SynchronizerService extends Service implements
                LatestCustomersReader.OnCustomerChangeListener {
        @Override
        public int onStartCommand(Intent intent, int flag, int startId) {
        Runnable runnable = new Runnable() {
            public void run() {
                mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(),
                        0,
                /*TICK_INTERVAL*/10000);
            }
        };
    
        Thread t = new Thread(runnable);
        t.run();
    
        return START_STICKY;
    }
    
    
    @Override
    public void customerAdded(Customer customer) {
        // Insert to DB or whatever you want
    }
    
    private class TimeDisplayTimerTask extends TimerTask {
        @Override
        public void run() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    try {
                        getProducts();   // Uses ProductReader
                        getCustomers();  // Uses LatestCustomerReader
                        // 
                        // ...
                        //
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            });
        }
    

    我希望它有用。 } }

    【讨论】:

      猜你喜欢
      • 2015-11-26
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      • 2015-07-18
      • 1970-01-01
      • 1970-01-01
      • 2012-04-13
      • 2020-04-23
      相关资源
      最近更新 更多