2017-04-12 103 views
0

我有一個類,它連接到Web服務並讀取最新數據。它是:從服務讀取Web服務響應以NetworkOnMainThreadException結束

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(); 
       } 
      } 
     }); 
    } 
} 
} 

謝謝先進。

回答

0

當應用程序嘗試在其主線程上執行聯網操作時,會引發此異常。在AsyncTask中運行你的代碼。

+0

我已經知道異常的原因,但我如何修復LatestProductReader類或服務以防止異常? –

+0

將LatestProductReader的基類更改爲AsyncTask並未解決問題 –

+0

您可以在Service類中看到AsyncTask的示例: http://stackoverflow.com/questions/22043652/using-an-asynctask-inside-a-service-類 –

0

我將這個回答發佈給未來的讀者。雖然它可以用不同的方法解決,但這個解決了我的問題。我繼承了閱讀器AsyncTask並創建了一個觀察者接口,爲每個接口通知用戶類(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(); 
       } 
      } 
     }); 
    } 

我希望它是有用的。 } }