Сохранить обновленное изображение из recyclerview и показать в автономном режиме Android

Я очень новичок в Android. В моем приложении у меня есть API для отдыха, который содержит информацию о пользователях компании. Например, имя, адрес электронной почты, телефон и т. д. Я также реализую изображение с этой информацией. Список изображений исходит из URL-адреса. Я использую библиотеку изображений Glide, чтобы показать эти изображения. Теперь проблема в том, что я использовал эту строку .diskCacheStrategy( DiskCacheStrategy.ALL) для кэширования изображения на устройстве. Он всегда показывает предыдущее сохраненное изображение. Я пробовал также с Пикассо. Но когда пользователь делает новую фотографию, изображение не обновляется. Поэтому пишу следующее.

 .skipMemoryCache( true )
 .diskCacheStrategy( DiskCacheStrategy.NONE )

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

У меня есть адаптер Glide для реализации следующим образом

Glide.with( holder.itemView.getContext() )
                    .load( Constants.HTTP.PHOTO_URL + currentColleague.getMail() )
                    .skipMemoryCache( true )
                    .diskCacheStrategy( DiskCacheStrategy.NONE )
                    .signature( new StringSignature( String.valueOf(Constants.HTTP.PHOTO_URL + currentColleague.getMail() ) ) )
                    .into( holder.colleaguePicture );

Есть ли способ сохранить изображение с URL-адреса и показать в reyclerview.

Может быть, это не связано, но я дал для понимания класса активности

    public class MyColleaguesPage extends AppCompatActivity implements MyColleaguesAdapter.ColleagueListListener{


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mycolleagues_layout);


        if (getNetworkAvailability()) {
            rq = Volley.newRequestQueue(this);

            recyclerView = this.findViewById(R.id.colleagues_recycler);
            recyclerView.setHasFixedSize(true);
            recyclerView.setLayoutManager(new LinearLayoutManager(MyColleaguesPage.this));
            recyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());

            myColleagueList = new ArrayList<>();

            sendRequest();

        } else {

            colleagueConfigViews();
        }


    public boolean getNetworkAvailability() {
        return Utils.isNetworkAvailable(getApplicationContext());
    }

    public void sendRequest() {

        trustAllCertificates();

        CookieHandler.setDefault( cookieManager );

        if (cookieManager==null) {

                }
            });
            AlertDialog alert = builder.create();
            alert.show();
        } else {
            JsonArrayRequest jsonArrayRequest = new JsonArrayRequest( Request.Method.GET, UPLOAD_URL + "/api/users", null, new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {

                    for (int i = 0; i < response.length(); i++) {

                        MyColleagueModel mycolleague = new MyColleagueModel();

                        try {
                            JSONObject object = response.getJSONObject( i );

                            mycolleague.setName( object.optString( "name" ) );
                            mycolleague.setGivenName( object.optString( "givenName" ) );
                            mycolleague.setCompany( object.optString( "company" ) );
                            mycolleague.setTitle( object.optString( "title" ) );
                            mycolleague.setMail( object.optString( "mail" ) );
                            mycolleague.setMobile( object.optString( "mobile" ) );
                            mycolleague.setDepartment( object.optString( "department" ) );

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }

                        myColleagueList.add( mycolleague );

                    }

                    adapter = new MyColleaguesAdapter( myColleagueList, MyColleaguesPage.this );

                    recyclerView.setAdapter( adapter );

                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.i( "Volley Error: ", error.toString() );
                }
            } );

            rq.add( jsonArrayRequest );
        }
    }

}

Обновленный ответ

 Glide.with( holder.itemView.getContext() )
                .load( Constants.HTTP.PHOTO_URL + currentColleague.getMail() )
                .skipMemoryCache(getNetworkAvailability())

                .signature( new StringSignature( String.valueOf(Constants.HTTP.PHOTO_URL + currentColleague.getMail() ) ) )
                .into( holder.colleaguePicture );



 public boolean getNetworkAvailability() {
    return Utils.isNetworkAvailable(context);
}

person TechoTek    schedule 08.03.2018    source источник
comment
Glide автоматически сохраняет изображения в кеше, не нужно об этом думать.   -  person Ravindra Pawar    schedule 08.03.2018
comment
@RavindraPawar да, я знаю. Но мой вопрос был не в этом. Я хотел бы сохранить изображение в бэкэнде. Но если онлайн, я хотел бы показать обновленное изображение. Вот почему я использую .diskCacheStrategy( DiskCacheStrategy.NONE ). Но теперь нет изображения в офлайне   -  person TechoTek    schedule 08.03.2018
comment
Есть ли способ, когда появится новое изображение, предыдущее загрузочное изображение будет переопределено?   -  person TechoTek    schedule 08.03.2018


Ответы (1)


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

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

GlideApp.with(fragment)
  .load(url)
  .placeholder(R.drawable.placeholder) // <-- this should fix
  .into(view);

Если у вас нет заполнителя, вы можете установить нулевое изображение в imageView:

imageView.setImageDrawable(null); //empty imageView

Это позволяет вам восстановить поведение кэша глиссады.

Почему это происходит? Представление переработчика будет повторно использовать строки, которые были показаны ранее, создавая странный эффект, который вы заметили. Представление изображения повторно используемой строки покажет предыдущее изображение, если вы не скажете glide немедленно показать что-то еще в качестве заполнителя.

Редактировать

Единственный способ заставить glide аннулировать кешированный ресурс — это использовать:

.signature()

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

Пример (из glide github):

Glide.with(yourFragment)
    .load(yourFileDataModel)
    .signature(new StringSignature("your signature string derived from the lastModifiedPicture timestamp"))
    .into(yourImageView);

Единственный способ.

person Tommaso Resti    schedule 08.03.2018
comment
Если я напишу .placeholder(R.drawable.placeholder) в этой строке, загрузка изображения займет слишком много времени. Моя проблема в том, что в Интернете можно увидеть изображения. Но когда я использовал .diskCacheStrategy (DiskCacheStrategy.ALL). он сохраняет изображения, а также я могу видеть файл. Но у меня есть функция загрузки фотографий. С этой строкой я не мог обновить картинку. - person TechoTek; 08.03.2018
comment
Как я могу обновить новое изображение и в то же время сохранить это обновленное изображение, чтобы переопределить предыдущее изображение - person TechoTek; 08.03.2018
comment
Я отредактировал вопрос. поведение такое же. сначала я запускаю приложение. И reyclerview показывает все изображения с URL-адресов. Я могу сохранить изображение так же, как и до изменения кода. Теперь загружаю новое изображение. и я иду recyclerview. Я вижу старый образ. не образ. Но если я напишу .diskCacheStrategy( DiskCacheStrategy.NONE ), я увижу последний образ. Но в оффлайне изображение пустое. там нет изображения - person TechoTek; 08.03.2018
comment
у вас есть какие-либо обновления для моего вопроса. Я действительно страдаю от этой проблемы с 2 дней - person TechoTek; 08.03.2018
comment
Вы пробовали решение, которое я написал во второй части моего ответа? - person Tommaso Resti; 09.03.2018
comment
Я использовал .signature(new StringSignature(Constants.HTTP.PHOTO_URL + currentColleague.getMail())), но это не работает. не могли бы вы рассказать мне, как я могу определить свою собственную StringSignature - person TechoTek; 16.03.2018
comment
я же говорил вам... вы должны использовать информацию, поступающую с сервера. Вы должны реализовать это. На самом деле вы используете строку, которая вам совсем не помогает. Строка подписи, которую вы создаете, не изменится, если изображение изменится на сервере. Скажите парню, который реализовал ваш внутренний код, чтобы он добавил поле временной метки в ваш ответ json с данными о пользователе, которое указывает, когда пользователь обновил изображение своего профиля, и использует это поле для создания подписи. - person Tommaso Resti; 21.03.2018