目前,我正在“优化”我的应用程序。我仍然是一个初学者,因此我所做的基本上是将方法从MainActivity.class移至其单独的类。我相信它的名称为Encapsulation
((如果我错了,请指正)。
我的应用程序需要:
android.intent.action.SEND
)。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中更新了它们的值也保持不变)。
我想知道两件事。
谢谢!
关于事件顺序的假设存在问题。 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),然后将其存储在名为YoutubeUsage
的ctx
实例变量中。
在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. }
}