Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: При загрузке большого количества картинок библиотекой Picasso заканчивается память

В общем делаю приложение, которое должно выводить посты пользователя. В этих постах есть картинки, все они должны качаться с интернета. Я сначала использовал UIL, но возникали проблемы с памятью. Подумал что другая библиотека поможет, нашёл Picasso. Но там оказалась та же проблема.

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

Что я только не пробовал. Думал может я не правильный способ выбрал вывода ленты. Но в итоге я для чистоты эксперимента упростил всё настолько, что выводятся только исключительно картинки в ImageView и ничего кроме них. Но после сороковой картинки память кончается и дальше ошибки.

Да, картинки достаточно большие. Я пробовал делать ресайз в Picasso. Да это помогает, но немного, через определённое количество картинок, снова кончается память. Разве что проблема не наблюдается, если сделать ресайз до 200 по ширине. Но такие мелкие картинки мне не нужны. По ширине картинки должны быть как минимум 480.

Также ещё: включил дебаг и на всех картинках стоит красный треугольник. Что означает что источник сеть.

Тестировал на андроид 4.1.1 и на 2.3.3. На обоих проблема, на 2.3.3 понятное дело ещё меньше картинок могут отобразиться. На 5.0 вообще всё нормально.

Я думал Picasso и подобные библиотеки как раз и предназначены для подобных задач, чтобы не было проблем с памятью. Хотя я наверное что-то делаю не так.

Вот код:
Java(TM) 2 Platform Standard Edition 5.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package com.freescribbler.freescribbler;
 
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.squareup.picasso.Picasso;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
 
 
public class HomeActivity extends Activity {
    serverAPI serverAPI1; //Класс запросов к серверу
    SharedPreferences myPref; //Настройки доступа к серверу
    final String USER_CONNECTID = "user_connectid"; //ID
    final String USER_TOKEN = "user_token"; //Токен
 
    int Counter; //Счётчик выведенных постов
 
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
 
        serverAPI1  = new serverAPI(); //инициализируем класс
        loadLoginData();//загружаем данные доступа к серверу
        Counter=0; //инициализируем счётчик
 
        Picasso.with(HomeActivity.this).setIndicatorsEnabled(true); //Включаем дебаг у пикассо
        new AsyncTaskGetPosts().execute();// Запускаем асинхронное выполнение загрузки данных с сервера, с последующим выводом постов
    }
 
    //Загружаем данные для запросов к серверу
    void loadLoginData() {
        myPref = getSharedPreferences("myPref", MODE_PRIVATE);
 
        //Проверяем, существует ли токен
        if (myPref.contains(USER_TOKEN)){
            serverAPI1.token = myPref.getString(USER_TOKEN, "");
            serverAPI1.connectid=myPref.getString(USER_CONNECTID,"");
            Log.e("Токен существует", serverAPI1.token);
        }
        else{
            serverAPI1.token =null;
            serverAPI1.connectid=null;
            Toast toast = Toast.makeText(getApplicationContext(),
                    "Пользователь не залогинен", Toast.LENGTH_LONG);
            toast.show();
            Log.e("Токена нет", "null");
        }
    }
 
 
    //Здесь мы получаем от сервера картинки
    public class AsyncTaskGetPosts extends AsyncTask<String,Void, String> {
        @Override
        //Создаём асинхронную задачу в фоне
        protected String doInBackground(String... params){
            return serverAPI1.loadPosts(50); //Запрашиваем 50 постов
        }
        @Override
        //То что выполнится по завершении фонового процесса
        protected void onPostExecute(String result){
            super.onPostExecute(result);
            //вызываем метод, где обрабатываем JSON и выводим картинки
            makePosts(result);
        }
    }
 
 
 
    //Метод вывода постов
    void makePosts (String postData){
        try {
            //Создаём объект JSON
            JSONObject jsnResp = new JSONObject(postData);
            JSONArray jposts = jsnResp.getJSONArray("data");
            //Цикл вывода картинок
            for (int i=0; i<jposts.length();i++){
                JSONObject curentPost = new JSONObject(jposts.getString(i));
 
                String picURL; //переменная для хранения ссылок на картинки
                //Узнаём дал ли сервер картинку
                if(curentPost.getString("pics").equals("-1")){
                    //При негативном результате ссылка будет null
                    Log.d("PICS","is -1");
                    picURL = null;
                }
                else {
                    //Позитивный результат
                    JSONArray picsInPost = curentPost.getJSONArray("pics");
                    JSONObject picTest = new JSONObject(picsInPost.getString(0));
                    //Вытаскиваем ссылку для картинки
                    picURL = picTest.getString("picname");
                    //Создаём ImageView
                    ImageView iv = new ImageView(this);
 
                    LinearLayout lL = (LinearLayout) findViewById(R.id.linearL);
                    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                            RelativeLayout.LayoutParams.WRAP_CONTENT,
                            RelativeLayout.LayoutParams.WRAP_CONTENT);
                    lL.addView(iv, lp); //Вставляем его в нужный Layout
                    //Загржаем картинку из интернета в ImageView
                    Picasso.with(HomeActivity.this)
                            .load(picURL) //ссылка
                            .placeholder(R.drawable.loading) //картинка загрузки
                            .error(R.drawable.error) //картинка ошибки
                            .into(iv); //сюда мы грузим картинку
                    Log.d("COUNTER", String.valueOf(Counter));
                    Counter++;
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}
Ответ:
Сообщение от Lumber
да, удаляются.


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


самому надо реализовать класс-адаптер.


должно работать. Если было переполнение памяти, надо смотреть как адаптер реализован, возможно он где-то ссылки на картинки сохранял...
Спасибо. Попробую потом ListView
Вопрос: Как отредактировать файл библиотеки

Здрасьте)

Столкнулся с такой проблемой. Есть библиотека Я хочу малость подредактировать ее, дабы убрать маску и лазер при сканировании qr-кода. В Android Studio редактировать файлы подключенной либы на лету нельзя, они там после декомпиляции остаются в формате .class, подключить эту либу в качестве модуля у меня не получилось, всплывает другая ошибка (пример ). Пытался выяснить, как в данном конкретном случае решить проблему, но то ли я чего-то не понимаю, то ли меня понять не могут:

Собственно, в итоге вопрос, что в данном случае вообще можно сделать (надо в либе файл ViewFinderView отредактировать, чтобы иметь возможность с ним потом взаимодействовать) или какие вообще есть адекватные способы редактирования отдельных файлов библиотеки или как можно отредактировать .class (не .java) файл? А, и наследоваться теоретически можно, но там связей куча, то есть переопределить методы только в нужном файле тоже не получится, придется наследоваться от разных классов и кучу методов переопределять, чтобы это все заработало. Поэтому про этот способ знаю, но надеюсь, что есть вариант попроще...
Ответ: Здравствуйте извините что так поздно отвечаю на ваше сообщение так как только увидел его. Чтобы открыть файл библиотеки вам нужно . Я пробовал открывать через них и у меня получалось.
Вопрос: Есть некая библиотека, сделана в QT. Как скомпилить под Андроид с использованием qt-lib?

Какие изменения нужно сделать в исходнике для компиляции под Андроид?
в либе используются классы:
#include <QString>
#include <QByteArray>
#include <QVector>
...и многие другие. В связи с чем, не хотелось бы всё переделывать на чистые плюсы.
Если прописать
#include "/home/user/ndkr10e/platforms/android-21/arch-arm/usr/include/jni.h"
то очень много ошибок компилер выдает:
/home/user/ndkr10e/platforms/android-21/arch-arm/usr/include/jni.h:776: error: '__NDK_FPABI__' does not name a type
__NDK_FPABI__ \
^

в таком духе.
EDIT: библиотека изначально строилась под Ubuntu.
Ответ: Со сборкой разобрался. Теперь возникла трудность с обратной связью:
Код Java(TM) 2 Platform Standard Edition 5.0
1
2
3
4
   public void onResult(String value)
    {
        Log.i("Log", "result from native code");
    }
- этот метод вызывается библиотекой. Пока его тип был void - оно работало, но с аргументами АПК падает (FATAL SIGNAL)
попытка выглядит вот так:
Код C++ (QT)
1
2
3
4
5
6
7
8
        jclass cls2 = env->FindClass("com/myclass/native/TRX");  // try to find the class
        jmethodID mid = env->GetMethodID(cls2, "onResult", "(Ljava/lang/String;)V");  // find method;
        usleep(1000*1000);
        jobject javaObjectRef = env->NewObject(cls2, mid);
        char *buf = (char*)malloc(10);
        strcpy(buf, "1234567890");
        jstring jstrBuf = (env)->NewStringUTF(buf);
        env->CallVoidMethod(javaObjectRef, mid, jstrBuf);
Как исправить?
Вопрос: Использование библиотеки (so) в исходниках на с++ с ndk

Добрый день.


Недавно разбираюсь с NDK. И возник вопрос.

У меня есть библиотека (1)(*.so), могу ли я ее подключить к NDK и использовать. Я понимаю что, когда я делаю ./ndk-build создается библиотека(2). Так вот мне надо что бы при создании библиотеки 2 использовалась библиотека 1. Надеюсь понятно объяснил. Подскажите, плиз, как это сделать.

Спасибо
Ответ:
Сообщение от russov
У меня есть библиотека (1)(*.so), могу ли я ее подключить к NDK и использовать.
Тебе надо не исходники тогда подключать, а скомпилированную библиотеку:
.
Вопрос: Интеграция библиотеки с GitHub в Студию

Гуру, дайте краткую инструкцию, пли-и-из!
(библиотеками раньше не пользовался - первые шаги и "первая паранойя")

Есть такое (рисует график)
compile 'com.github.blackfizz:eazegraph:1.2.2@aar'
...Успешно встраивается в dependencies и работает

Хочу научиться СКАЧИВАТЬ подобные библиотеки к себе и подключать их проекту из папки (а не отслеживать каждый раз "обновления" на сайте).

Можете пошаговый процесс описать? Хотя-бы "на пальцах"???
библиотеку с скачал... архивчиком... Куда класть? (в либы? в корень?) как подключать? Какую из папок библиотеки указывать?(всю папку или *Library?) Может можно уже "авто-скаченное" из папкок "билда" использовать? может можно в dependencies просто указать пусть на распакованное?

Конечная цель: Хочу чужую либу встроить в мои исходники! Чтобы РЯДОМ лежали, а не в билдах! И чтобы не зависили от наличия проекта на гитхабе (или вообще инернета)

Не по теме:

Попробовал сам... в результате потребовала докачать целых 2 версии других версий андроида в SDK, хотя через dependencies запускалось, а потом вообще чуть не потерял проект на каких-то ошибках (пока вручную все упоминания из файлов проекта не вычистил)



Не по теме:

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

Ответ:
Сообщение от REALIST07
5 минут заняло:
спасибо! проверю!
(я раньше ВООБЩЕ не использовал чужие библиотеки и не создавал своих - еще не до конца понимаю их структуру чтобы знать что нужно удалять)
Вопрос: организация библиотеки

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

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

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

Ответ:
Цитата(cppGhost @  21.11.2014,  13:01 )
а) в каком-то сервере, который будет хранить информацию о книгах и том, кто что уже покупал
б) в каком-то сайте-админке, через который можно будет пополнять библиотеку (то есть платным контентом)


По идее подходит любая система для выкладывания/продажи файлов.
Достаточно быстро реализуется в связке MySQL + PHP + Любой Шлюз Оплаты
Вопрос: Установка библиотек в android-studio

Всем привет,есть небольшая проблема.Нашёл один интересный урок: .
Там говорится про парсинг,я установил библиотеку Json,но не знаю где скачать библиотеку "apache".Помогите,пожалуйста(ругается на этот импорт):

Java(TM) 2 Platform Standard Edition 5.0
1
2
3
4
5
6
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
Ответ: Кроме того, сама студия рекомендует делать все эти дела через Gradle
Но чаще всего, там где есть Мавен есть и Гредл. Погугли про "Gradle подключение библиотек"
Вопрос: Как объявить статический класс?

В Android Studio заметил интересную вещь, есть некий класс (AlertDialog.Builder), объявлен как static, но в то же время можно создавать его экземпляр. Как такое может быть? Я знаком со статическими полями, методами, а вот можно ли объявлять весь класс статическим? Пробовал сделать это в Eclipse-подчеркивает красным, не дает. Помогите пожалуйста разобраться
Ответ: Статический внутренний класс должен обращаться к нестатическим членам своего внешнего класса при помощи объекта, т.е. он не может обращаться напрямую на нестатические члены своего внешнего класса(тоесть объект внемшего класса не создаётся)

Внутренний класс(non-static) имеет доступ ко всем переменным и методам своего внешнего класса и может непосредственно ссылаться на них(значит объект внешнего класса создаётся и существует, как минимум, пока существует объект внутреннего класса). Если вам понадобится получить ссылку на объект внешнего класса, запишите имя внешнего класса, за которым следует точка, а затем ключевое слово this.

Вопрос: В чем преимущество использования библиотеки GSON перед стандартными средствами парсинга JSON?

В чем преимущество использования библиотеки GSON перед JSONObject JSONArray то есть перед стандартными средствами парсинга JSON ??
Ответ: Вот в которой обсуждаются все преимущества и недостатки основных видов библиотек для работы JSON
Вопрос: Класс не видит ресурсы через контекст

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

Приложение при первом запуске создаёт БД. Соответственно есть 2 класса-синглтона:
MyApplication унаследованный от Application - класс для преинициализации всего что мне нужно будет в дальнейшем, в т.ч. вызов класса Db;
Db унаследованный от SQLiteOpenHelper для работы с БД. Всё тривиально, реализованы методы onCreate и onUpgrade + мои собсвенные.

Я не хотел хардкодить SQL-инструкции ни в классе MyApplication ни в Db, а убрал их в string-array в в xml-файл с ресурсами в res\values-ru. Доступ к массиву получаем
Java
1
String[] groupArray = context.getResources().getStringArray(R.array.groups);
Так вот в классе MyApplication массив groupArray формируется нормально, а в классе Db нет. Если попытаться вызвать метод getResources() происходит ошибка:

java.lang.RuntimeException: Unable to create application com.android.tools.fd.runtime.BootstrapApplication: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference

Но ведь я получаю контекст методом getApplicationContext() в классе MyApplication и передаю его параметром при вызове класса Db. Там в классе Db в конструкторе ссылка на контекст присваивается приватному полю context. По идее должно работать. Но нет.

Файл с массивом SQL-инсертов:
XML
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="groups">
        <item>Insert into groups (groups,group_runame) VALUES (\'string1\',\'string1\')</item>
          ................................................................................................................
        <item>Insert into groups (groups,group_runame) VALUES (\'string2\',\'string2\')</item>
    </string-array>
</resources>
MyApplication
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package ru.arvalon.mytraining;
 
import android.app.Application;
import android.util.Log;
import android.widget.ArrayAdapter;
 
/**
 * Created by arvalon on 04.05.2016.
 */
public class MyApplication extends Application {
 
    private static  MyApplication singleton;
    private Db db;
 
    public static MyApplication getInstance(){
        return singleton;
    }
 
 
    @Override
    public void onCreate() {
        super.onCreate();
        singleton=this;
        db=Db.getInstance(getApplicationContext());
        
        String[] groupArray = getResources().getStringArray(R.array.groups); // ТУТ РАБОТАЕТ!
        for(int i=0;i<groupArray.length;i++){
            db.addGroup(groupArray[i]);
        }
    }
}
Класс Db
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package ru.arvalon.mytraining;
 
import android.app.Application;
import android.content.ContentValues;
import android.content.Context;
import android.content.res.Resources;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import android.widget.ArrayAdapter;
 
public class Db extends SQLiteOpenHelper {
 
    private Context context;
    public static Db instance;
 
    private Db(Context context) {
        super(context, DB_NAME, null, VERSION);
        getWritableDatabase();
        this.context=context;
    }
 
    public static Db getInstance(Context context){
        if (instance==null){
            instance= new Db(context);
        }
        return instance;
    }
 
    @Override
    public void onCreate(SQLiteDatabase db) {
        
        String[] groupArray = context.getResources().getStringArray(R.array.groups); // НА ЭТОЙ СТРОЧКЕ ОШИБКА
       
    }
 
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        
    }
 
    public void addGroup(String group){
        SQLiteDatabase db=getWritableDatabase();
        try {
            db.beginTransaction();
            db.execSQL(group);
 
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }
    }
}
Немного почистил классы от лишнего кода, оставил только прохождение к методу onCreate базы и строчку с ошибкой в нём.
Можете подсказать, почему не доступны ресурсы в классе Db, ошибка NullPointerException?
Ответ:
Сообщение от Паблито
this.context=context;
getWritableDatabase();
Действительно, заработало! Спасибо!

Добавил в конструктор getWritableDatabase() т.к. БД SQLLite не создаётся пока что-нибудь не вызвать с getWritableDatabase(), но отдельный метод-заглушку с getWritableDatabase() в классе Db писать не хотел. Опытным путём просто добавил getWritableDatabase() без какой-либо ссылки в конструктор, но добавлять надо было после инициализации поля context.