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

Android Бесконечное управление памятью списков

Я реализую бесконечный список, загружая больше элементов в arraylist в методе onScrollStateChanged (...). Если я реализую эту схему для получения более 1 миллиона записей, у меня будет миллион объектов, добавленных в arraylist, который будет интенсивным в памяти. Какие схемы можно использовать для эффективного управления памятью?

PS: Вопрос о количестве элементов, которые можно поместить в адаптер. Edit:

Подробнее:

Источником данных является Интернет. Мне нужно получить данные из Интернета и поместить их в адаптер списка.

4b9b3361

Ответ 1

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

Когда вы прокручиваете список, выбираете больше записей и обновляете кеш по-прежнему (не получаете 1 миллион за один раз).

Ответ 2

В Android виртуализируется ListView. Практически это означает, что нет фактического предела для количества элементов внутри него. Вы можете положить миллионы строк внутри списка, он будет выделять только память для в настоящее время видимые (или несколько других вершин).

Источник

Также проверьте эту статью Рекомендации по производительности для списка андроидов ListView

Ответ 3

Этот вопрос не имеет ничего общего с емкостью Adapter. Вместо этого это связано с объемом памяти, выделенной вашим приложением.

Он имеет зарезервированную кучу, чтобы выделить объекты, если вы пройдете этот предел, вы получите Исключение из памяти

Здесь небольшой тест, он может дать вам представление о количестве данных, которые вы могли бы выделить. Но имейте в виду, что в этом примере объект содержит только String, если бы это было великолепное Bitmap количество объектов для размещения было бы намного меньше.

//MemoryActivity

public class MemoryActivity extends Activity {

    private List<TestObject> _testObjects = new ArrayList<TestObject>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_memory);
        coolGuysDoNotLookBackAtExplosion();
        starCountdown();
    }

    private void starCountdown() {
        new CountDownTimer(300000, 500) {

            public void onTick(long millisUntilFinished) {
                TextView tv_watcher = (TextView) findViewById(R.id.tv_watcher);
                tv_watcher.setText(getMemoryUsage());
            }

            public void onFinish() {
                starCountdown();
            }

        }.start();
    }

    private String getMemoryUsage() {
        String heapSize = String.format("%.3f", (float) (Runtime.getRuntime().totalMemory() / 1024.00 / 1024.00));
        String freeMemory = String.format("%.3f", (float) (Runtime.getRuntime().freeMemory() / 1024.00 / 1024.00));

        String allocatedMemory = String
                .format("%.3f", (float) ((Runtime.getRuntime()
                        .totalMemory() - Runtime.getRuntime()
                        .freeMemory()) / 1024.00 / 1024.00));
        String heapSizeLimit = String.format("%.3f", (float) (Runtime.getRuntime().maxMemory() / 1024.00 / 1024.00));

        String nObjects = "Objects Allocated: " + _testObjects.size();

        return "Current Heap Size: "    + heapSize
                + "\n Free memory: "
                + freeMemory
                + "\n Allocated Memory: "
                + allocatedMemory
                + "\n Heap Size Limit:  "
                + heapSizeLimit
                + "\n" + nObjects;
    }

    private void coolGuysDoNotLookBackAtExplosion(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                _testObjects = new ArrayList<TestObject>();
                while (true) {
                    _testObjects.add(new TestObject());
                }
            }
        }).start();
    }
}

//TestObject

public class TestObject {
    private String sampleText = "Lorem Ipsum is simply dummy text of the printing and typesetting industry";
}

Ответ 4

Если ваш ListView содержит только текстовые элементы, вам нечего делать. Однако, если вы загружаете больше насыщенных памяти, например drawables (например, у вас есть изображение с правой стороны вашего вида), то вам следует сделать некоторую переработку, чтобы получить лучший результат. Вы можете получить OutOfMemoryException очень быстро на более слабом устройстве. Я мог бы пойти OOM даже на Nexus 4. Просто попробуйте прокрутить очень быстро, вверх и вниз, вверх и вниз, и повторите, пока сила не закроется.

Взгляните на RecyclerListener, его очень легко реализовать.

Ответ 5

Вы должны использовать кнопки paging и Load More в качестве нижнего колонтитула ListView. Например:

url = http://your_full_url.php?page=1

скажем, у вас есть 100 записей на каждой странице, а затем в первый раз получите все эти 100 записей page 1, покажите их на ListView и cache им. Теперь прокрутите вниз свой ListView и нажмите кнопку "Загрузить еще" (кнопка "Загрузить больше" должна быть установлена ​​как нижний колонтитул ListView).

Когда вы нажмете на Load More, вы получите следующие 100 записей, вызвав

url = http://your_full_url.php?page=2 и т.д. для

url = http://your_full_url.php?page=3,

url = http://your_full_url.php?page=4 и т.д.

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

Ответ 6

Я предполагаю, что sqlite Database и потоковый анализатор (GSON).

Ответ 7

Я не смог найти точное число, упомянутое в документах. Однако возвращаемые типы всех Adapter#getCount() (посмотрите подклассы): ints.

Поэтому мы можем сильно подозревать, что вы можете добавить до Integer.MAX_VALUE элементы в адаптер, который составляет 2 31 -1 (более 2 миллиардов). Адаптеры используют Lists и Maps для хранения данных внутри, которые имеют одинаковый предел.

Поэтому вы не должны беспокоиться об ограничениях адаптера, а не использовать слишком много памяти. Я предлагаю вам загрузить 10-100 элементов в адаптер и просто добавить больше элементов, как только пользователь достигнет нижней части списка.

Ответ 8

Подход Tianwei - это путь.

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

Если бы вы сохранили все данные в памяти, что бы было проблемой ленивой загрузки ListView? Просто загрузите все данные и пропустите ленивую загрузочную часть... Конечно, при ленивом подходе загрузки, который загружает только видимые данные (и, возможно, еще несколько), вам нужно будет выполнить ленивую загрузку внизу и в верхней части списка, чтобы сделать эту работу.

Теперь, когда нет информации о характере данных (текст, изображения) или источника (Интернет, SQLite Db, текстовый файл...), я не могу дать вам код (образцы), как это реализовать. Если вы уточняете данные, я могу более точно ответить на вопрос.

Ответ 9

Если вам нужно сохранить в памяти 1M объекты и предполагать, что данные объекта малы, то это всего лишь несколько МБ памяти, и должно быть хорошо, чтобы просто хранить в памяти. Из вопроса я понимаю, что вы будете читать больше элементов, когда пользователи прокручиваются вперед, поэтому на практике у вас не будет 1M строк - пользователям потребуется прокрутить в течение длительного времени, чтобы добраться до 1M. До тех пор, пока вы правильно используете ListView, вы можете заставить данные адаптера стать 1M + строк в памяти без каких-либо проблем.