Подтвердить что ты не робот

Извлечение большого количества данных, каков наилучший способ?

У меня есть число URL Мне нужно получить данные, это должно происходить по порядку, один за другим. Количество данных, возвращаемых путем запроса этих URL, относительно велико. Мне нужно перенести определенные загрузки, которые не удались.

Каков наилучший способ? Должен ли я использовать IntentService, Loaders или что-то еще?

Дополнительное примечание: мне нужно будет не только загружать, но и обрабатывать данные (создавать таблицы в db, заполнять их данными и т.д.). Поэтому DownloadManger не может помочь.

4b9b3361

Ответ 1

Я бы использовал IntentService.

Он имеет ряд преимуществ, которые подходят для ваших нужд, в том числе возможность загрузки данных без запуска вашего приложения и поддержки автоматического перезапуска службы с помощью setIntentRedelivery().

Вы можете установить несколько идентификаторов для конкретного задания, вам нужно выполнить с помощью Intent дополнительных функций, и вы можете отслеживать прогресс с помощью SharedPreferences - таким образом вы также можете возобновить работу, если она была отменена ранее.

Ответ 2

Самый простой способ - это, вероятно, использовать систему DownloadManager http://developer.android.com/reference/android/app/DownloadManager.html

(отвечая с моего телефона, поэтому, пожалуйста, извините отсутствие форматирования)

Ответ 3

Я бы предложил услугу для этого. Обслуживание службы разрешает многие проблемы.

  • Это позволит сообщать о прогрессе асинхронно для приложения, чтобы вы могли включить или отключить определенный gui в приложении на основе состояния загрузки данных

  • Это позволит вам продолжить загрузку, даже если пользователь переключится на другое приложение или закрывает приложение.

  • Позволит вам установить независимую связь с сервером, чтобы приоритезировать загрузки без участия пользователя.

Ответ 4

Попробуйте WakefulIntentService для создания долгого задания, которое использует wakelocks для сохранения вашей задачи и выполнения https://github.com/commonsguy/cwac-wakeful. p >

Кроме того, если весь процесс приложения будет убит, вы можете захотеть посмотреть на сохранение очереди задач на диск, используя что-то вроде Tape, from Square

Ответ 5

Я думаю, что путь к загрузке - это загрузка URL-адресов в массив, а затем запуск AsyncTask, возвращающий логическое значение в onPostExecute, указывающее, имеет ли операция успех или нет. то, сохраняя глобальный индекс int, вы можете запустить AsyncTask со следующим индексом, если успех или тот же индекс в противном случае. Вот псевдокод

private int index=0;
//this array must be loaded with urls
private ArrayList<String> urlsArray;

new MyDownloaderAsyncTask().execute(urlsArray.get(index));


class MyDownloaderAsyncTask extends AsyncTask<String,String,Boolean>{

@Override
doInBackground(String... input){

//downlaod my data is the function which download data and return a boolean
return downloadMyData();

}

@Override
onPostExecute(Boolean result){

if(result)
    new MyDownloaderAsyncTask().execute(urlsArray.get(++index));
else
    new MyDownloaderAsyncTask().execute(urlsArray.get(index));
}


}

надеюсь, что эта помощь

Ответ 6

Я только что закончил библиотеку с открытым исходным кодом, которая может делать именно то, что вам нужно. Используя droidQuery, вы можете сделать что-то вроде этого:

$.ajax(new AjaxOptions().url("http://www.example.com")
                        .type("GET")
                        .dataType("JSON")
                        .context(this)
                        .success(new Function() {
                            @Override
                            public void invoke($ droidQuery, Object... params) {
                                //since dataType is JSON, params[0] is a JSONObject
                                JSONObject obj = (JSONObject) params[0];
                                //TODO handle data
                                //TODO start the next ajax task
                            }
                        })
                        .error(new Function() {
                            @Override
                            public void invoke($ droidQuery, Object... params) {
                                AjaxError error = params[0];
                                //TODO adjust error.options before retry:
                                $.ajax(error.request, error.options);
                            }
                        }));

Вы можете указать другие типы данных, которые будут возвращать разные типы объектов, такие как JSONObject, String, Document и т.д.

Ответ 7

Подобно @Murtuza Kabul, я бы сказал, пользуюсь сервисом, но это немного сложнее. У нас есть аналогичная ситуация, связанная с постоянным доступом в Интернет и обновлениями, хотя наша компания уделяет больше внимания поддержанию работы службы. Я попытаюсь выделить основные функции, не слишком сильно утопив вас (и код принадлежит компании;))

  • android.permission.RECEIVE_BOOT_COMPLETED и BroadcastReceiver прослушивание android.intent.action.BOOT_COMPLETED для пробуждения службы.

  • Не связывайте службу с Activity, вы хотите, чтобы она работала все время. например, мы называем context.startService(new Intent(context.getApplicationContext(), OurService.class))

  • Класс сервиса - это просто класс, который регистрирует и вызывает OurServiceHandler (как в нашем случае мы запускаем повторные проверки, а Handler управляет "тиками" )

  • У нас есть OurServiceRunnable, который является одноэлементным, который проверяется и вызывается Handler для каждого теста. Он защищает от перекрывающихся обновлений. Он делегирует OurServiceWorker для фактического подъема.

Звучит тяжело, но вы хотите, чтобы служба всегда работала, всегда отмечая (через Handler), но только за одну проверку. Вы также столкнетесь с проблемой базы данных, если используете стандартную парадигму SqlLite DbHelper, так как вы не можете открыть БД на нескольких потоках, а определенно хотите, чтобы доступ в Интернет был отключен от основного потока. Наш хак был java.util.concurrent.locks.ReentrantLock защитой доступа к БД, но вы, вероятно, могли бы поддерживать доступ к БД в потоке пользовательского интерфейса и выполнять операции DB через Handler.

Помимо всего прочего, это просто вопрос о том, как загружать атомы в терминах "получить задачу, загрузить задачу, выполнить задачу" или включить ее из отказавшего состояния, например, загрузить "ОК", попытаться завершить.

Ответ 8

Вы должны взглянуть на библиотеку волейбола:

http://www.javacodegeeks.com/2013/06/android-volley-library-example.html

Есть также интересное видео автора, которое состоялось в google io 2013:

http://www.youtube.com/watch?v=yhv8l9F44qo

В основном потому, что он облегчает процесс управления множеством таких брезгливых задач, которые являются проверкой соединения, прерыванием соединения, управлением очередью, повторением, возобновлением и т.д.

Цитата из javacodegeeks "Преимущества использования Volley:

  • Волейбол автоматически планирует все сетевые запросы. Это означает, что Volley будет следить за всеми сетевыми запросами, которые приложение выполняет для получения ответа или изображения из Интернета.
  • Volley обеспечивает прозрачное кэширование дисков и памяти.
  • Volley предоставляет мощный API запросов отмены. Это означает, что вы можете отменить один запрос или вы можете отменить блокировку или область запросов.
  • Volley предоставляет мощные возможности настройки.
  • Volley предоставляет инструменты для отладки и отслеживания

Обновление от dennisdrew: Для большого файла лучше использовать вариант залпа, который разрешает использование другой реализации клиента клиента. Эта ссылка дает более подробную информацию:

Волейбольная статья об этой модификации:

http://ogrelab.ikratko.com/android-volley-examples-samples-and-demos/

Подробный файл github:

https://github.com/ogrebgr/android_volley_examples/blob/master/src/com/github/volley_examples/toolbox/ExtHttpClientStack.java

Ответ 9

public class FetchDataFromDBThread implements Runnable {

    /*
     * Defines the code to run for this task.
     */
    @Override
    public void run() {
        // Moves the current Thread into the background
        android.os.Process
                .setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);

        FetchDataFromDB();
    }

}