使用NetworkOnMainThreadException

时间:2017-04-12 07:57:17

标签: android multithreading exception networking service

我有一个连接到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();
               }
           }
       });
   }
 }
}

先谢谢。

2 个答案:

答案 0 :(得分:0)

当应用程序尝试在其主线程上执行网络操作时,抛出此异常。在AsyncTask中运行代码。

答案 1 :(得分:0)

我将这个答案发布给未来的读者。虽然它可以用不同的方法解决,但这个解决了我的问题。我从 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();
                }
            }
        });
    }

我希望它有用。     }     }