【发布时间】:2020-08-24 11:53:35
【问题描述】:
现在,我正在“优化”我的应用程序。我仍然是一个初学者,所以我所做的基本上是将方法从我的 MainActivity.class 移动到它们单独的类。我相信它叫Encapsulation (如果我错了,请纠正我)。
我的应用程序需要:
- 从 YouTube 应用获取 YouTube 播放列表链接(带有 Intent,
android.intent.action.SEND)。 - 使用该链接通过 YouTubeApi 和 Volley 从 Google 服务器获取数据。
- 读取收到的数据并将其添加到
arrayList<String>。
我的YouTubeUsage.java 类应该做的是使用 YouTubeApi 和 Volley 获取数据,然后使用 SharedPreferences 存储数据。保存数据后,将使用我的方法getVideoIds() 在我的ConvertActivity.class(这是专门为android.intent.action.SEND 创建的活动)中读取数据,然后在我的createRecyclerView() 方法中为我的listView 设置适配器。
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 中更新了这些值,这些值也保持不变。
我想知道两件事。
- 如何解决这个问题?
- 这是最有效的方法(优化)吗? (我想也许 使用 Gson 将 VolleyResponse 转换为字符串,然后存储字符串文件,但我不知道这是否是最好的方法,因为它应该是 临时数据。感觉和以前差不多)。
谢谢!
【问题讨论】:
-
我可以建议一个简化的开始吗?在您的
fetch方法中,将sharedPreferences(response, context)行替换为updateSharedPreferences(response, context),然后删除方法sharedPreferences。结果将是相同的,但流程会更加清晰。其次,您的onResponse方法是否被成功调用,正如您所期望的那样,并且使用有意义的response字符串;在这个方法的第一行放一个Log.d()来检查。 -
我将
sharedPreferences(response, context)替换为updateSharedPreferences(response, context)。onResponse方法被正确调用:我检查了Log.d("ResponseCheck", response);并返回完整的 JSON 文件。但是,android.intent.action.SEND需要多次调用才能真正在 logcat 中显示响应。如果我使用带有android.intent.action.SEND的不同 YouTube 链接,JSON 不会更新。我对它为什么这样做感到困惑。是因为 SharedPreferences 还是 Volley Request? -
也许您的 RequestQueue 在收到响应之前就超出了范围。将声明
RequestQueue queue;放在类级别,而不是在您的fetch方法中。 -
我已将
RequestQueue queue;置于类级别(低于public class YouTubeUsage{)并将fetch方法的第一行更改为queue = Volley.newRequestQueue(context);。截至目前,当应用程序在后台运行时 JSON 不会更新(当我处理多任务时。我可能应该实现OnPause?)但是当我关闭应用程序并再次打开它时它会更新。但是,即使我从 Volley 收到正确的响应,recyclerView 仍然显示来自先前响应的数据...它仅在我关闭应用程序并再次执行时显示正确的数据... -
尝试将您对
createRecyclerView的调用转移到您的 Activity 的onResume方法中。
标签: json android-studio youtube-api sharedpreferences android-volley