【问题标题】:Is there a way to fetch data from api call once in retrofit?有没有办法在改造中从 api 调用中获取数据?
【发布时间】:2019-03-07 16:12:23
【问题描述】:

我在导航抽屉中有一个 Fragment,在 onCreate 方法中有一个改造 api 调用来从服务器获取一些数据。

ApiInterface apiService = ApiClient.getClient(false).create(ApiInterface.class);
    Call<MoviesWrapper> call = apiService.getMovies("upcoming", PreferencesHelper.getLanguage(context), "US");
    call.enqueue(new Callback<MoviesWrapper>() {
        @Override
        public void onResponse(Call<MoviesWrapper> call, Response<MoviesWrapper> response) {
            MoviesWrapper moviesWrapper = response.body();
            assert moviesWrapper != null;
            final HomeAdapter moviesAdapter = new HomeAdapter(getContext(), moviesWrapper.getMovies(), null, true);
            moviesRv.setAdapter(moviesAdapter);
            progressBar1.setVisibility(View.GONE);
        }

        @Override
        public void onFailure(Call<MoviesWrapper> call, Throwable t) {
            Log.e(Constants.STRINGS.FAILURE, t.toString());
        }
    });

我的问题是每次进入片段时,retrofit 都会从服务器获取数据。有没有办法在改造中缓存数据而不是每次都调用api?

【问题讨论】:

标签: android android-fragments retrofit retrofit2 android-networking


【解决方案1】:

您可以在activity中调用API并将响应传递给fragment,它可以防止每次对fragment的递归调用。

你可以分享一些代码,我会提供详细的解决方案。

【讨论】:

    【解决方案2】:

    Retrofit 本身无法缓存获取的数据。最好的方法是获取它们,然后使用例如保存在本地数据库中。房间持久性库或领域。

    策略应该是这样的:

    1. 检查本地数据库中的数据是否存在。
    2. 如果不获取它们并保存在本地数据库中
    3. 从本地数据库加载数据并显示在屏幕上

    您还应该创建负责此功能的类。并实现回调/侦听器,它将这些类中的数据提供给您的片段。因为在 Activity 或 Fragment 中实现 API 调用是不好的选择。它在开发中造成了巨大的混乱。

    【讨论】:

    • 不幸的是,这不是一个非常有效的解决方案,因为每次用户打开应用程序时我都会进行 api 调用(数据可能已更改,因此我需要从 api 调用中获取新数据) .您的解决方案意味着我为每个 Api 调用以及每次用户打开应用程序时执行所有这些操作。
    • 您可以添加另一个 API 调用,该调用将返回更改时间戳并将此值与本地数据库中的时间戳进行比较。然后仅当获取的时间戳在本地之前才获取新数据。此解决方案可保护您免受网络访问。因为即使网络不可用,您总是有一些本地数据库中的数据要显示
    • 这将是我的解决方案,但不幸的是我正在使用我无法控制的 TMDb api。我的想法是创建一个包含 api 响应的单例类。所以我会遵循你建议的相同过程,但在单例类中使用它。会不会对性能有很大影响?
    • 或者将lastFetchTime作为参数添加到当前API调用中。并在服务器上添加一些逻辑。例如。如果参数为空,则返回所有数据,否则如果没有任何更改,则返回空列表
    • 你看到Android系统可以随时杀死你的应用程序。当它完成时,您的所有静态变量也会消失。有趣的是,应用程序可以被杀死,并且您不会从 MAIN LAUNCHER 活动重新启动。如果用户没有专门杀死该应用程序,该应用程序将保留在最近使用的应用程序中,并且用户可以从它暂停的活动中重新启动它。然后,如果您尝试使用单例中的数据,您将抛出 NullPointerException
    【解决方案3】:

    如果您的数据没有从 API 更改,那么您可以将数据存储到 SharedPreferences 或本地数据库中,或者您可以将数据序列化到 ObjectSerializer(ByteArrayInputStream/ByteArrayOutputStream. 如果数据正在更改,那么您可以将 Firebase 推送通知实现为推送将到来,然后可以点击该 API,您将获得该数据。希望它能让您了解根据您的要求可以在所有这些中使用什么

    【讨论】:

      【解决方案4】:

      1.将这两行添加到 build.gradle(app)

      implementation 'com.squareup.retrofit2:retrofit:2.1.0'
      implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
      

      2。创建以下结构

      ->API
              ->ApiClient
              ->ApiInterface      
      ->database
              ->dbHelper
              ->itemDB
      ->models
              ->IitemResult
              ->restItems
      

      3. ApiCleint.java

      package test.com.testapp.API;
      
      import retrofit2.Retrofit;
      import retrofit2.converter.gson.GsonConverterFactory;
      
      public class APIClient {
      
          public static final String BASE_URL = "TEST_URL";
          private static Retrofit retrofit = null;
      
          public static Retrofit getClient()
          {
              if (retrofit == null)
              {
                  retrofit = new Retrofit.Builder()
                          .baseUrl(BASE_URL)
                          .addConverterFactory(GsonConverterFactory.create())
                          .build();
              }
              return retrofit;
      
          }
      }
      

      4. ApiInterface.java

      package test.com.testapp.API;
      
      import retrofit2.Call;
      import retrofit2.Retrofit;
      import retrofit2.http.GET;
      import test.com.testapp.models.IItemResult;
      
      public interface ApiInterface {
          @GET("String id")
          Call<IItemResult> getItems();   
      
      }
      

      5. dbHelper.java

      package test.com.testapp.database;
      
      import android.content.ContentValues;
      import android.content.Context;
      import android.database.Cursor;
      import android.database.sqlite.SQLiteDatabase;
      import android.database.sqlite.SQLiteOpenHelper;
      
      import java.util.ArrayList;
      import java.util.List;
      
      import test.com.testapp.models.restItems;
      
      public class dbHelper extends SQLiteOpenHelper {
      
          private static final int DATABASE_VERSION = 1;
          private static final String DATABASE_NAME = "DsTest";
      
          public dbHelper(Context context) {
              super(context, DATABASE_NAME, null, DATABASE_VERSION);
          }
      
          @Override
          public void onCreate(SQLiteDatabase sqLiteDatabase) {
              sqLiteDatabase.execSQL(ItemDB.CREATE_TABLE);
          }
      
          @Override
          public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
      
              sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + ItemDB.TABLE_NAME);
              onCreate(sqLiteDatabase);
          }
      
          public long InsertItem(restItems restItem){
              SQLiteDatabase db = this.getWritableDatabase();
              ContentValues values = new ContentValues();
              values.put(ItemDB.COLUMN_BRAND_DEC, restItem.getBrandDesc());
              values.put(ItemDB.COLUMN_MRP, restItem.getmRP());
              values.put(ItemDB.COLUMN_VAT_RATE, restItem.getVatRate());
      
              long id = db.insert(ItemDB.TABLE_NAME, null, values);
      
              db.close();
      
              return id;
          }
      
          public List<restItems> getItemList(){
      
              List<restItems> restItems =new ArrayList<>();
      
              String selectQuery = "SELECT  * FROM " + ItemDB.TABLE_NAME + " ORDER BY " +
                      ItemDB.COLUMN_ID + " DESC";
      
              SQLiteDatabase db = this.getWritableDatabase();
              Cursor cursor = db.rawQuery(selectQuery, null);
      
              if (cursor.moveToFirst()) {
                  do {
                      restItems item = new restItems();
                      //   item.setId(cursor.getInt(cursor.getColumnIndex(Note.COLUMN_ID)));
                      item.setBrandDesc(cursor.getColumnName(1));
                      item.setmRP(cursor.getColumnName(2));
                      item.setVatRate(cursor.getColumnName(3));
      
                      restItems.add(item);
                  } while (cursor.moveToNext());
              }
      
              db.close();
      
              return restItems;
          }
      }
      

      6. ItemDb.java

      package test.com.testapp.database;
      
      public class ItemDB {
      
          public static final String TABLE_NAME = "items";
      
          public static final String COLUMN_ID = "id";
          public static final String COLUMN_BRAND_DEC = "brand_dec";
          public static final String COLUMN_MRP = "mrp";
          public static final String COLUMN_VAT_RATE = "vat_rate";
      
          private String Id;
          private String Brand_Desc;
          private String Mrp;
          private String Vat_rate;
      
          public ItemDB(String id, String brand_Desc, String mrp, String vat_rate) {
              Id = id;
              Brand_Desc = brand_Desc;
              Mrp = mrp;
              Vat_rate = vat_rate;
          }
      
          public ItemDB() {
          }
      
          public String getId() {
              return Id;
          }
      
          public void setId(String id) {
              Id = id;
          }
      
          public String getBrand_Desc() {
              return Brand_Desc;
          }
      
          public void setBrand_Desc(String brand_Desc) {
              Brand_Desc = brand_Desc;
          }
      
          public String getMrp() {
              return Mrp;
          }
      
          public void setMrp(String mrp) {
              Mrp = mrp;
          }
      
          public String getVat_rate() {
              return Vat_rate;
          }
      
          public void setVat_rate(String vat_rate) {
              Vat_rate = vat_rate;
          }
      
          public static final String CREATE_TABLE =
                  "CREATE TABLE " + TABLE_NAME + "("
                  + COLUMN_ID + "INTEGER PRIMARY KEY AUTO INCREMENT,"
                  + COLUMN_BRAND_DEC + "TEXT,"
                  + COLUMN_MRP + "TEXT,"
                  + COLUMN_VAT_RATE + "TEXT"
                          + ")";
      }
      

      7. restItems.java

      package test.com.testapp.models;
      
      import com.google.gson.annotations.SerializedName;
      
      public class restItems {
      
          @SerializedName("Brand")
          private String brand;
          @SerializedName("MRP")
          private String mrp;
          @SerializedName("VAT")
          private String vat;
      
          public restItems(String brand, String mrp, String vat) {
              this.brand = brand;
              this.mrp = mrp;
              this.vat = vat;
          }
      
          public restItems() {
          }
      
          public String getBrand() {
              return brand;
          }
      
          public void setBrand(String brand) {
              this.brand = brand;
          }
      
          public String getMrp() {
              return mrp;
          }
      
          public void setMrp(String mrp) {
              this.mrp = mrp;
          }
      
          public String getVat() {
              return vat;
          }
      
          public void setVat(String vat) {
              this.vat = vat;
          }
      
          @Override
          public String toString() {
              return "restItems{" +
                      "brand='" + brand + '\'' +
                      ", mrp='" + mrp + '\'' +
                      ", vat='" + vat + '\'' +
                      '}';
          }
      }
      

      8. IItemResult .java

      package test.com.testapp.models;
      
      import com.google.gson.annotations.SerializedName;
      
      import java.util.List;
      
      public class IItemResult {
          @SerializedName("iItemResult")
          private List<restItems>iItemResult = null;
      
          public IItemResult(List<restItems> iItemResult) {
              this.iItemResult = iItemResult;
          }
      
          public void setiItemResult(List<restItems> iItemResult) {
              this.iItemResult = iItemResult;
          }
      
          public List<restItems> getiItemResult() {
              return iItemResult;
          }
      }
      

      9. MainActivity.java

      package test.com.testapp;
      
      import android.os.AsyncTask;
      import android.support.v7.app.AppCompatActivity;
      import android.os.Bundle;
      import android.util.Log;
      import android.view.View;
      import android.widget.Button;
      import android.widget.ProgressBar;
      
      import retrofit2.Call;
      import retrofit2.Callback;
      import retrofit2.Response;
      import test.com.testapp.API.APIClient;
      import test.com.testapp.API.ApiInterface;
      import test.com.testapp.database.dbHelper;
      import test.com.testapp.models.IItemResult;
      
      public class MainActivity extends AppCompatActivity {
      
          private Button getData;
          private ProgressBar bar;
          private dbHelper db;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              getData = (Button)findViewById(R.id.btnGet);
              bar = (ProgressBar)findViewById(R.id.pBar);
      
              getData.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View view) {
                      new insertData().execute("");
                  }
              });
      
          }
      
          private class insertData extends AsyncTask<String, Void, String>
          {
              @Override
              protected void onPreExecute() {
                  bar.setVisibility(View.VISIBLE);
              }
      
              @Override
              protected String doInBackground(String... strings) {
                  ApiInterface apiInterface = APIClient.getClient().create(ApiInterface.class);
      
                  db = new dbHelper(getApplicationContext());
      
                  Call<IItemResult>resultCall = apiInterface.getItems();
                  resultCall.enqueue(new Callback<IItemResult>() {
                      @Override
                      public void onResponse(Call<IItemResult> call, Response<IItemResult> response) {
                          System.out.println("MAIN_ACTIVITY"  + response.body().getiItemResult().size());
                          System.out.println(response.body().getiItemResult().get(1));
      
                          for (int i=0; i<response.body().getiItemResult().size(); i++)
                          {
                              db.InsertItem(response.body().getiItemResult().get(i));
                          }
      
                          System.out.println("DB_RESULT: " + db.getItemList());
                      }
      
                      @Override
                      public void onFailure(Call<IItemResult> call, Throwable t) {
      
                      }
                  });
                  return null;
              }
      
              @Override
              protected void onPostExecute(String s) {
                  super.onPostExecute(s);
      
                  bar.setVisibility(View.GONE);
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-04
        • 1970-01-01
        • 2022-10-14
        • 2019-09-29
        相关资源
        最近更新 更多