Intent Service блокирует пользовательский интерфейс и вызывает ANR - PullRequest
0 голосов
/ 03 июля 2019

Мне нужно загрузить некоторые данные, как только пользователь войдет в приложение.Я поставил - сетевые вызовы для загрузки этих данных и - транзакции базы данных, чтобы записать их в sqlite

в службе намерений.Данные огромны, поэтому их сохранение в sqlite занимает много времени.Но мне интересно, почему служба намерений блокирует пользовательский интерфейс.Я не могу перемещаться по приложению.Если я нажимаю на любую кнопку, ничего не происходит.Если я нажимаю снова, приложение просто зависает и в конечном итоге вызывает ANR.

Я использовал Сервис ранее.Поскольку служба работает в основном потоке, я использую IntentService.У меня были одновременные AsyncTasks для загрузки каждого набора данных.Теперь я избавился от этих AsyncTasks и обработал все сетевые вызовы в методе onHandleIntent.Я тестирую на устройстве Android версии 5.1.1 (леденец).

public class MastersSyncService extends IntentService {
private static final String TAG = "MastersSyncService";
private static final int CUSTOMERS_PAGE_LENGTH = 5000;

private Context mContext;
private DataSource dataSource;
private boolean isReset;
private ProgressDialog pDialog;
private int numOfCustReceived, pageNumber, customersVersion;
private AlertDialog alertDialog;

public MastersSyncService() {
    super(TAG);
}

@Override
protected void onHandleIntent(Intent intent) {
    mContext = MastersSyncService.this;
    dataSource = new DataSource(mContext);

    if (intent.getExtras() != null) {
        isReset = intent.getBooleanExtra("isReset", false);
    }
    customersVersion = dataSource.customers.getVersion();
    if (customersVersion == 0) {
        dataSource.customers.truncateTable();
    }

    downloadPackingDataMasters();
    downloadCommoditiesMasters(); //makes a network call and writes some simple data to sqlite
    downloadPaymentTypesMasters(); //makes a network call and writes some simple data to sqlite
    downloadReasonsMasters(); //makes a network call and writes some simple data to sqlite
    downloadMeasurementTypesMasters(); //makes a network call and writes some simple data to sqlite
    downloadDocketsMasters(); //makes a network call and writes some simple data to sqlite
    downloadContractsMasters(); //makes a network call and writes some simple data to sqlite
    downloadBookingModesMasters(); //makes a network call and writes some simple data to sqlite
    downloadPincodeMasters(); //makes a network call and writes some simple data to sqlite
    downloadCustomersMasters(); //this method has a recursive network call with pagination. Takes a lot of time

}

public void downloadCustomersMasters() {
    try {

        Globals.lastErrMsg = "";
        String url = VXUtils.getCustomersUrl(customersVersion, pageNumber);
        Utils.logD("Log 1");

        InputStream inputStream = HttpRequest.getInputStreamFromUrlRaw(url, mContext);
        if (inputStream != null) {
            pageNumber++;
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            dataSource.beginTransaction();
            String line = null;
            while ((line = reader.readLine()) != null) {
                if (Utils.isValidString(line)) {
                    numOfCustReceived++;
                    Utils.logD("line from InputStream: " + line);
                    parseCustomer(line);
                }
            }
            dataSource.endTransaction();
        } else {
            numOfCustReceived = 0;
            Utils.logD(TAG + " InputStream is null");
        }
    } catch (IOException ioe) {
        ioe.printStackTrace();
        System.out.println("Exception while reading input " + ioe);
    } catch (Exception e) {
        e.printStackTrace();
        if (!Utils.isValidString(Globals.lastErrMsg))
            Globals.lastErrMsg = e.toString();
        if (Globals.lastErrMsg.equalsIgnoreCase("null"))
            Globals.lastErrMsg = getString(R.string.server_not_reachable);
    }

    if (numOfCustReceived >= CUSTOMERS_PAGE_LENGTH) {
        downloadCustomersMasters();
    } else {
        if (!Utils.isValidString(Globals.lastErrMsg) && pDialog != null && pDialog.isShowing()) {
            Utils.updateTimeStamp(mContext, Constants.CUSTOMERS_DATE_PREF);
        }
    }
}

public void downloadPackingDataMasters() {
    try {

        Globals.lastErrMsg = "";

        int version = dataSource.packingData.getVersion();
        String url = VXUtils.getPackingDataUrl(version); //, imei, versionCode + ""
        Utils.logD("Log 1");
        PackingDataResponse response = (PackingDataResponse) HttpRequest
                .getInputStreamFromUrl(url, PackingDataResponse.class,
                        mContext);

        if (response != null) {
            Utils.logD("Log 4");
            Utils.logD(response.toString());
            if (response.isStatus()) {
                List<PackingDataModel> data = response.getData();
                if (Utils.isValidArrayList((ArrayList<?>) data)) {
                    if (isReset)
                        dataSource.packingData.truncateTable();
                    int val = dataSource.packingData.savePackingData(data, version);
                }
            } else {
                Globals.lastErrMsg = response.getMessage();
            }
        }

    } catch (Exception e) {
        if (!Utils.isValidString(Globals.lastErrMsg))
            Globals.lastErrMsg = e.toString();
        if (Globals.lastErrMsg.equalsIgnoreCase("null"))
            Globals.lastErrMsg = getString(R.string.server_not_reachable);
    }

    if (!Utils.isValidString(Globals.lastErrMsg)) {
        Utils.updateTimeStamp(mContext, Constants.PACKING_DATE_PREF);
    }

}

private final char DEFAULT_QUOTE_CHARACTER = '"';
private final char DEFAULT_SEPARATOR_CHARACTER = ',';

private void parseCustomer(String line) {

    char quotechar = DEFAULT_QUOTE_CHARACTER;
    char separator = DEFAULT_SEPARATOR_CHARACTER;
    if (line == null) {
        return;
    }

    List<String> tokensOnThisLine = new ArrayList<String>();
    StringBuffer sb = new StringBuffer();
    boolean inQuotes = false;
    for (int i = 0; i < line.length(); i++) {

        char c = line.charAt(i);
        if (c == quotechar) {
            if (inQuotes && line.length() > (i + 1)
                    && line.charAt(i + 1) == quotechar) {
                sb.append(line.charAt(i + 1));
                i++;
            } else {
                inQuotes = !inQuotes;
                if (i > 2 && line.charAt(i - 1) != separator
                        && line.length() > (i + 1)
                        && line.charAt(i + 1) != separator) {
                    sb.append(c);
                }
            }
        } else if (c == separator && !inQuotes) {

            if (Utils.isValidString(sb.toString())) {
                String str = sb.toString().trim();
                tokensOnThisLine.add(str);
            } else {
                tokensOnThisLine.add(sb.toString());
            }
            sb = new StringBuffer();
        } else {
            sb.append(c);
        }
    }

    if (Utils.isValidString(sb.toString())) {
        String str = sb.toString().trim();
        tokensOnThisLine.add(str);
    } else {
        tokensOnThisLine.add(sb.toString());
    }
    int customerId = Integer.parseInt(tokensOnThisLine.get(0));
    String custName = tokensOnThisLine.get(2);
    Utils.logD("CUST: " + customerId + " " + custName);
    dataSource.customers.saveCustomerDirect(
            customerId,
            tokensOnThisLine.get(1),
            custName,
            tokensOnThisLine.get(3),
            tokensOnThisLine.get(4),
            tokensOnThisLine.get(5),
            tokensOnThisLine.get(6),
            tokensOnThisLine.get(7),
            Integer.parseInt(tokensOnThisLine.get(8)),
            Integer.parseInt(tokensOnThisLine.get(9)),
            Integer.parseInt(tokensOnThisLine.get(10)),
            Integer.parseInt(tokensOnThisLine.get(11)),
            Integer.parseInt(tokensOnThisLine.get(12)));
}

Загрузка данных занимает несколько минут.Я не могу заставить пользователя ждать так долго.Пожалуйста, предложите, как сделать пользовательский интерфейс интерактивным, пока данные загружаются в фоновом режиме.Или, пожалуйста, предложите способы быстрого сохранения большого количества записей в sqlite

...