如何使用SharedPreferences正确处理数据管理?

问题描述 投票:0回答:1

目前,我正在“优化”我的应用程序。我仍然是一个初学者,因此我所做的基本上是将方法从MainActivity.class移至其单独的类。我相信它的名称为Encapsulation ((如果我错了,请指正)

我的应用程序需要:

  1. 从YouTube应用程序中获取YouTube播放列表链接(意图android.intent.action.SEND)。
  2. 使用该链接通过YouTubeApi和Volley从Google服务器获取数据。
  3. 读取接收到的数据并将其添加到arrayList<String>

我的YouTubeUsage.java类应该做的是使用YouTubeApi和Volley获取数据,然后使用SharedPreferences存储数据。保存数据后,将在我的ConvertActivity.class方法中为listView设置适配器之前,使用我的方法android.intent.action.SEND在我的getVideoIds()(这是专门为createRecyclerView()创建的活动)中读取数据。

YouTubeUsage.java

public class YoutubeUsage {

    private Boolean results = false;
    private String mResponse;
    private ArrayList<String> videoIds = new ArrayList<>();
    String Url;

    public String getUrl(String signal) {
        String playlistId = signal.substring(signal.indexOf("=") + 1);
        this.Url = "https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails%2C%20snippet%2C%20id&playlistId=" +
                playlistId + "&maxResults=25&key=" + "API_KEY";

        return this.Url;
    }            

    public void fetch(String Url, final Context context){
        RequestQueue queue = Volley.newRequestQueue(context);
        StringRequest request = new StringRequest(Request.Method.GET, Url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        sharedPreferences(response, context);
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("VolleyError", Objects.requireNonNull(error.getMessage()));
            }
        });
        queue.add(request);
    }
    private void sharedPreferences(String response, Context context){
        SharedPreferences m = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = m.edit();
        if (m.contains("serverResponse")){
            if (!m.getString("serverResponse", "").equals(response)){
                editor.remove("serverResponse");
                editor.apply();
                updateSharedPreferences(response, context);
            }
        } else{
            updateSharedPreferences(response, context);
        }

    }
    private void updateSharedPreferences(String mResponse, Context mContext){
        SharedPreferences m = PreferenceManager.getDefaultSharedPreferences(mContext);
        SharedPreferences.Editor editor = m.edit();
        editor.putString("serverResponse", mResponse);
        editor.apply();
    }
}

ConvertActivity.java

public class ConvertActivity extends AppCompatActivity {

    YoutubeUsage youtubeUsage = new YoutubeUsage();
    ArrayList<String> videoIDs = new ArrayList<>();

    String Url = "";

    ListView listView;
    MyCustomAdapter myCustomAdapter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_convert);
        listView = findViewById(R.id.listview_convert);
        Intent intent = getIntent();
        String action = intent.getAction();
        String type = intent.getType();
        if ("android.intent.action.SEND".equals(action) && "text/plain".equals(type)) {
            Url = youtubeUsage.getUrl(Objects.requireNonNull(intent.getStringExtra("android.intent.extra.TEXT")));
        }
        //I would like to avoid the try/catch below       
        try {
            videoIDs = getVideoIDs(Url, this);
            createRecyclerView(videoIDs);
            Log.i("ResponseVideoIDs", String.valueOf(videoIDs.size()));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private ArrayList<String> getVideoIDs(String Url, Context context) throws JSONException {
        ArrayList<String> rawVideoIDs = new ArrayList<>();
        youtubeUsage.fetch(Url, context);
        SharedPreferences m = PreferenceManager.getDefaultSharedPreferences(context);
        String serverResponse = m.getString("serverResponse", "");
        JSONObject jsonObject = new JSONObject(serverResponse);
        JSONArray jsonArray = jsonObject.getJSONArray("items");
        for (int i = 0; i<jsonArray.length(); i++){
            JSONObject jsonObject1 = jsonArray.getJSONObject(i);
            JSONObject jsonVideoId =  jsonObject1.getJSONObject("contentDetails");
            rawVideoIDs.add(jsonVideoId.getString("videoId"));
        }
        return rawVideoIDs;
    }
    private void createRecyclerView(ArrayList<String> videoIDs){
        myCustomAdapter = new MyCustomAdapter(this, videoIDs);
        listView.setAdapter(myCustomAdapter);
        myCustomAdapter.notifyDataSetChanged();

    }
}

一切正常,但是,我的sharedPreferences从未更新。这意味着,如果我将YouTube播放列表从YouTube应用共享到我的应用(其中包含3个项目),则可以正常运行。 Listview将显示3个项目及其相应的ID。但是,如果我再次共享YouTube播放列表,则我的应用仍会保留我共享的上一个播放列表的数据(即使我将其关闭),也会显示项目编号和上一个链接的ID。如果我继续反复分享相同的播放列表,它将最终显示正确的项目数和正确的ID。

我可以将YouTubeUsage.java中的所有方法全部放入ConvertActivity.class中,这使我无法使用SharedPreferences在两个java类之间传输数据。但是,JSON引发异常。这意味着我必须用try / catch封装我的代码。我想避免这种情况,因为我需要对Volley刚收到的数据进行很多操作(检查类大小,查找某些字符串)。我发现在这些try / catch中执行此操作并不像我想要的那样。 (即,在try / catch之外,即使我在try / catch中更新了它们的值也保持不变)。

我想知道两件事。

  1. 如何解决此问题?
  2. 这是最有效的方法(优化)吗? (尽管我也许用Gson将VolleyResponse转换为字符串然后存储String文件,但是我不知道这是否是最好的方法,因为它应该是临时数据。感觉就像更多一样)。

谢谢!

json android-studio youtube-api sharedpreferences android-volley
1个回答
0
投票

关于事件顺序的假设存在问题。 Volley将异步处理请求,因此建议在此处实现观察者模式。

创建一个仅包含以下内容的新Java文件:

interface MyNetworkResponse {
   void goodResponse(String responseString);
}

然后确保ConvertActivity implements MyNetworkResponse并创建方法:

void goodResponse(String responseString) {
   // handle a positive response here, i.e. extract the JSON and send to your RecyclerView.
}

在您的活动范围内。

YoutubeUsage构造函数中,传递Activity上下文(YoutubeUsage),然后将其存储在名为YoutubeUsagectx实例变量中。

onCreate中,创建YoutubeUsage的实例并传递this

onResponse中,只需调用ctx.goodResponse(response)

将以下块修改为:

if ("android.intent.action.SEND".equals(action) && "text/plain".equals(type)) {
        Url = youtubeUsage.getUrl(Objects.requireNonNull(intent.getStringExtra("android.intent.extra.TEXT")));
        youtubeUsage.fetch(Url);
}

try/catch中删除onCreate

并且完全不需要使用SharedPreferences。>>

更新

尝试此代码:

MyNetworkResponse.java

interface MyNetworkResponse {
    void goodResponse(String responseString);
    void badResponse(VolleyError error);
}

YoutubeUsage.java

class YoutubeUsage {

private RequestQueue queue;
private MyNetworkResponse callback;

YoutubeUsage(Object caller) {
    this.callback = (MyNetworkResponse) caller;
    queue = Volley.newRequestQueue((Context) caller);
}

static String getUrl(String signal) {
    String playlistId = signal.substring(signal.indexOf("=") + 1);
    return "https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails%2C%20snippet%2C%20id&playlistId=" + playlistId + "&maxResults=25&key=" + "API_KEY";
}

void fetch(String url){
    StringRequest request = new StringRequest(Request.Method.GET, url,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    callback.goodResponse(response);
                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            callback.badResponse(error);
        }
    });
    queue.add(request);
}

}

ConvertActivity.java

public class ConvertActivity extends AppCompatActivity implements MyNetworkResponse {

YoutubeUsage youtubeUsage;
ArrayList<String> videoIDs = new ArrayList<>();

ListView listView;
MyCustomAdapter myCustomAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_convert);
    listView = findViewById(R.id.listview_convert);
    youtubeUsage = new YoutubeUsage(this);
    Intent intent = getIntent();
    String action = intent.getAction();
    String type = intent.getType();
    if ("android.intent.action.SEND".equals(action) && "text/plain".equals(type)) {
        String url = YoutubeUsage.getUrl(Objects.requireNonNull(intent.getStringExtra("android.intent.extra.TEXT")));
        youtubeUsage.fetch(url);
    }
}

private ArrayList<String> getVideoIDs(String serverResponse) throws JSONException {
    ArrayList<String> rawVideoIDs = new ArrayList<>();
    JSONObject jsonObject = new JSONObject(serverResponse);
    JSONArray jsonArray = jsonObject.getJSONArray("items");
    for (int i = 0; i < jsonArray.length(); i++) {
        JSONObject jsonObject1 = jsonArray.getJSONObject(i);
        JSONObject jsonVideoId = jsonObject1.getJSONObject("contentDetails");
        rawVideoIDs.add(jsonVideoId.getString("videoId"));
    }
    return rawVideoIDs;
}

private void createRecyclerView(ArrayList<String> videoIDs) {
    myCustomAdapter = new MyCustomAdapter(this, videoIDs);
    listView.setAdapter(myCustomAdapter);
    myCustomAdapter.notifyDataSetChanged();
}

@Override
public void goodResponse(String responseString) {
    Log.d("Convert:goodResp", "[" + responseString + "]");
    try {
        ArrayList<String> rawVideoIDs = getVideoIDs(responseString);
        createRecyclerView(rawVideoIDs);
    } catch (JSONException e) {
        // handle JSONException, e.g. malformed response from server.
    }
}

@Override
public void badResponse(VolleyError error) {
    // handle unwanted server response.
}

}

© www.soinside.com 2019 - 2024. All rights reserved.