Intereting Posts
Android.Share для социальных сетей Изменить элементы навигационного ящика внутри фрагмента Получайте события касания в диалоге, который отображается сам, когда палец уже касался экрана Ошибка «Файл пакета не был правильно подписан» – обнаружит, произойдет ли это с приложением Google Play app apk Всего страниц арены для JIT – что это значит? Как изменить источник ImageView в android Android WebView падает при нажатии на ссылку Разница между setTranslationX / Y и offsetLeftAndRight / offsetTopAndBottom? OnStop вызван до onStart Как автоматически добавлять тысячи разделителей, поскольку число вводится в EditText Как печатать локальный часовой пояс в posix формате в java (android)? Мобильный бэкэнд-стартер – добавьте в AppEngine Blobstore Corners ImgeView, встроенный в CardView, не имеет радиуса, как и углы CardView на Android С использованием библиотеки android.support.v4 в идее Intellij Как передать переменную в новую декларацию Runnable?

Как заставить Volley NetworkImageView работать в автономном режиме

Я использую Volley NetworkImageView для загрузки изображений из Интернета и просмотра в моем listview . Теперь я хочу, чтобы Volley NetworkImageView показывал сохраненные изображения, когда нет доступной сети. Volley уже кэшировал изображения по URL как ключ, потому что, когда я использую

 Entry entry = SingletonRequestQueue.getInstance(context).getRequestQueue().getCache().get(imageURL); 

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

 Bitmap b = BitmapFactory.decodeByteArray(entry.data, 0, entry.data.length); 

Потому что он создает много задержек, и мне нужно изобретать колесо, потому что снова я должен создать asynctask увидеть, когда listview прокручивается, чтобы отменить декодирование, переработать bitmap , создать в кеше памяти, найти наилучшее значение …

Поэтому лучше Idea – это просто сделать некоторые трюки, которые заставят Volley NetworkImageView использовать собственную DiskLRUCache, чтобы показать их, когда нет сети.

Есть идеи?

Мой код:

 public class SingletonRequestQueue { private static SingletonRequestQueue mInstance; private RequestQueue mRequestQueue; private ImageLoader mImageLoader; private static Context mCtx; private LruBitmapCache mLruBitmapCache; private SingletonRequestQueue(Context context) { mCtx = context; mRequestQueue = getRequestQueue(); mLruBitmapCache = new LruBitmapCache(LruBitmapCache.getCacheSize(context)); mImageLoader = new ImageLoader(mRequestQueue,mLruBitmapCache); } public static synchronized SingletonRequestQueue getInstance(Context context) { if (mInstance == null) { mInstance = new SingletonRequestQueue(context); } return mInstance; } public RequestQueue getRequestQueue() { if (mRequestQueue == null) { // getApplicationContext() is key, it keeps you from leaking the // Activity or BroadcastReceiver if someone passes one in. mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext(),new OkHttpStack()); // mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext()); } return mRequestQueue; } public <T> void addToRequestQueue(Request<T> req) { getRequestQueue().add(req); } public ImageLoader getImageLoader() { return mImageLoader; } public LruBitmapCache getLruBitmapCache() { return mLruBitmapCache; } public void setLruBitmapCache(LruBitmapCache lruBitmapCache) { mLruBitmapCache = lruBitmapCache; } } 

И в моем адаптере:

 public IssueListAdapter(Context context, int resource, List<Issue> objects) { super(context, resource, objects); this.context = context; this.mIssueList = objects; mImageLoader = SingletonRequestQueue.getInstance(context).getImageLoader(); } public static class ViewHolder{ public NetworkImageView mNetworkImageView; public TextView mFee; public TextView mName; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if(convertView == null){ holder = new ViewHolder(); LayoutInflater inflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.gridview_issuelist_item, parent, false); holder.mNetworkImageView = (NetworkImageView)convertView.findViewById(R.id.NetworkImageView_MainActivity_issue_image); holder.mName = (TextView)convertView.findViewById(R.id.TextView_MainActivity_name); holder.mFee = (TextView)convertView.findViewById(R.id.TextView_MainActivity_fee); Utility.settingTypfaceFont(context, holder.mName); Utility.settingTypfaceFont(context, holder.mFee); convertView.setTag(holder); }else{ holder = (ViewHolder)(convertView.getTag()); } final Issue issue = mIssueList.get(position); holder.mName.setText(issue.getTitle()); holder.mFee.setText(String.valueOf(issue.getFee())); String imageURL = issue.getPublicCover(); holder.mNetworkImageView.setImageUrl(imageURL, mImageLoader); holder.mNetworkImageView.setDefaultImageResId(R.drawable.placeholder2);; /* Entry entry = SingletonRequestQueue.getInstance(context).getRequestQueue().getCache().get(imageURL); if(entry != null && entry.data != null){ byte[] imageByte = entry.data; loadBitmap(imageByte, holder.mNetworkImageView,imageURL); }else{ holder.mNetworkImageView.setImageUrl(imageURL, mImageLoader); }*/ return convertView; } @Override public int getCount() { if(mIssueList != null){ return mIssueList.size(); } else{ return 0; } } public List<Issue> getIssueList() { return mIssueList; } } 

Просто добавьте эту строку в класс BasicNetwork

 if (!ConnectivityUtils.isNetworkEnabled(CardApplication.getContext()) && request instanceof ImageRequest) { VolleyLog.e("Cached response", "No Network Connectivity for Url=", request.getUrl()); return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, request.getCacheEntry().data, responseHeaders, true); } 

И для истечения срока действия данных вы можете изменить Cached.Entry, используя собственный HttpHeaderParser

Вот ссылка, которая подробно объясняет ситуацию

Я предпочитаю использовать Volley / retrofit с Android-Universal-Image-Loader / Picasso , загрузчики изображений отлично справились с загрузкой и кэшированием изображений.

По умолчанию они обрабатывают все с помощью одной строки кода:

 Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView); 

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

Когда вы перезагружаете приложение в автономном режиме, последнее, на что вы можете положиться только на Disk Cache (т.е. DiskBasedCache ). Локальный кэш Volley состоит из сетевых данных и заголовков ответов. Но в этой ситуации нам просто нужно сосредоточиться на заголовке Cache-Control . Например, если серверная сторона возвращает этот заголовок «Cache-Control: max-age = 604800», это говорит, что Volley кэширует ресурс ответа на 604800 секунд (источник в HttpHeaderParser.parseCacheHeaders () ). Затем, в следующий раз, когда мы получим данные одного и того же url, будет проверяться, превысило ли время истечения срока кэша, наконец, решить получить из сети или локально.

Следуйте своим описаниям, я полагаю, что ваша серверная сторона доставляет вам такое значение, как Cache-Control:must-revalidate|proxy-revalidate|no-cache|no-store , поэтому вы не можете повторно использовать последние извлеченные данные, когда вы были в не в сети.

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

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

Если нет, я предлагаю вам перейти на другую библиотеку, которая выполнит эту задачу. И на самом деле у вас может быть ваш друг, это Netroid . Он основан на Volley и предлагает несколько улучшений, которые не заставят вас сильно изменить свой текущий код. При этом управление временем истечения срока действия было бы намного проще, и было бы доступно больше функций.

 mImageLoader = new SelfImageLoader(mRequestQueue, mLruBitmapCache) { @Override public void makeRequest(ImageRequest request) { // you can manipulate the cache expire time with one line code. request.setCacheExpireTime(TimeUnit.DAYS, 10); // you can even according to the different request to // set up the corresponding expire time. if (request.getUrl().contains("/for_one_day/")) { request.setCacheExpireTime(TimeUnit.DAYS, 1); } else { request.setCacheExpireTime(TimeUnit.DAYS, 10); } } }; 

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

Здравствуйте @mmlooloo Я создал проект, который использует DiskLRUCache и Volley . Вот ссылка моего репозитория DiskLRUCache с помощью Volley . Надеюсь, это поможет вам показать сохраненное изображение. Благодарю.

  1. Поиск в Интернете для «android, как проверить подключение к Интернету»
  2. Реализовать это и проверить его в вашей реализации кэша (например, LruCache ). if(networkAvailable()){ getFromNetwork()} else { getFromCache()}

Логика в порядке? То просто попробуйте.
Кажется, что ваш класс кеша – LruBitmapCache .

То как насчет возможности проверки соединения в этом классе?

 public Bitmap getBitmap(String url) { if(networkAvailable()/* this is your impl */){ // dont use cache return null; } return getFromCache(); // or something like that; } 

Если я правильно вас понимаю, вам будет полезно, если кеш памяти, предоставленный классу ImageLoader который используется вашим NetworkImageView будет сохраняться между запусками приложений, не теряя при этом факта, что это кеш памяти .

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

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

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

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

  1. Каждый раз, когда putBitmap() вызывается вместе с вашей обычной операцией, сохраняйте закодированную версию растрового изображения на диске в фоновом потоке / AsyncTask .
  2. Каждый раз, когда растровое изображение удаляется из кеша (я предполагаю, что у вас есть какое-то ограничение пространства в кеше), удалите этот файл с диска в фоновом потоке / AsyncTask .
  3. Создайте задачу «loadFromDisk», которая будет выполняться в фоновом режиме каждый раз, когда создается кеш памяти (один раз для запуска приложения), чтобы заполнить кеш памяти доступными изображениями с диска.

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

Помогает ли вам это?