我的应用程序创建以下布局:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = this;
try {
setContentView(R.layout.main);
} catch (RuntimeException ex) {
ex.printStackTrace();
Toast.makeText(activity, getString(R.string.install_from_google_play), Toast.LENGTH_LONG).show();
finish();
return;
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/webv"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/browser_page"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/title"
android:text="@string/comments_page"
android:textStyle="bold"
android:textSize="22sp"
android:gravity="center_horizontal"
android:layout_below="@id/browser_page"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/user_view"
android:background="@null"
android:layout_margin="10dp"
android:listSelector="@android:color/darker_gray"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/title" />
<ProgressBar
android:id="@+id/retrievedCommentsProgressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
android:indeterminate="true"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recent_comments_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="10dp"
android:background="@null"
android:listSelector="@android:color/darker_gray"
android:visibility="invisible" />
<com.chiaramail.opencomments.MovableFloatingActionButton
android:id="@+id/add_comment"
android:visibility="visible"
app:fabSize="normal"
app:srcCompat="@drawable/plus_circle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:layout_marginTop="50dp"
android:layout_marginEnd="10dp"
android:layout_alignParentEnd="true"
android:layout_centerHorizontal="true" />
<com.chiaramail.opencomments.MovableFloatingActionButton
android:id="@+id/return_to_list"
android:visibility="invisible"
app:fabSize="normal"
app:srcCompat="@drawable/view_list_outline"
android:layout_below="@+id/add_comment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:layout_marginTop="50dp"
android:layout_marginEnd="10dp"
android:layout_alignParentEnd="true"
android:layout_centerHorizontal="true" />
<Button
android:id="@+id/refresh"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/refresh" />
<ImageView
android:id="@+id/back"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_margin="10dp"
android:layout_width="50dp"
android:layout_height="50dp"
app:srcCompat="@drawable/chevron_left_disabled" />
<ImageView
android:id="@+id/forward"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_margin="10dp"
android:layout_width="50dp"
android:layout_height="50dp"
app:srcCompat="@drawable/chevron_right_disabled" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
android:indeterminate="true"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"/>
</RelativeLayout>
我在 onCreate() 中声明以下 RecyclerView:
final ArrayList<UserComments> pageItemList = new ArrayList<>();
itemArrayAdapter = new CommentsAdapter(this, activity, pageItemList);
user_view = findViewById(R.id.user_view);
user_view.setAdapter(itemArrayAdapter);
user_view.addItemDecoration(new DividerItemDecoration(activity,
DividerItemDecoration.VERTICAL));
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
user_view.setLayoutManager(linearLayoutManager);
代码最终调用方法 fetchComments() 将数据加载到 pageItemList 中。
获取评论():
private void fetchComments(String url) {
String extractedURL = extractSite(url);
spinner.setVisibility(View.VISIBLE);
String extractedSite = extractSite(url);
String extractedDomain = extractDomain(url);
// If the URL doesn't have a host name, e.g., example.com, add "www." to the url and look for
// comments for either one.
if (extractedSite.equals(extractedDomain)) extractedSite = "www." + extractedDomain;
String mobileSite = "m." + extractedDomain;
Query commentQuery = baseRef.whereIn(FSHOSTNAME, Arrays.asList(extractedSite, mobileSite, extractedDomain));
registration = commentQuery.addSnapshotListener(new EventListener<QuerySnapshot>() {
@Override
public void onEvent(@Nullable QuerySnapshot value,
@Nullable FirebaseFirestoreException e) {
if (mFirebaseUser == null || value.size() == 0) {
if (blacklistArray.contains(extractDomain(url))) {
mActionBar.setBackgroundDrawable(new ColorDrawable(redToolbarColor));
showScamWarning(url);
retrieved_comments_dialog.show();
}
spinner.setVisibility(View.INVISIBLE);
return;
}
if (e != null) {
Log.w(TAG, "Listen failed.", e);
Toast.makeText(activity, "user_ID = " + user_ID, Toast.LENGTH_LONG).show();
Toast.makeText(activity, getString(R.string.listen_error) + BLANK + e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
spinner.setVisibility(View.INVISIBLE);
return;
}
// Display the "Loading comments..." message the first time only.
if (!registrations.containsKey(url)) Toast.makeText(activity, getString(R.string.loading_comments), Toast.LENGTH_SHORT).show();
boolean isEmpty = true;
ArrayList tmp = (ArrayList) docRefList.clone();
docRefList.clear();
userDocList.clear();
pageURLList.clear();
pageItemList.clear();
for (QueryDocumentSnapshot doc : value) {
if (!isSamePage(doc, url)) continue;
// Don't include duplicates.
for (int i = 0; i < tmp.size(); i++) {
if (!((QueryDocumentSnapshot)tmp.get(i)).getId().equals(doc.getId()) &&
!docRefList.contains(doc)) {
isEmpty = false;
getUserValuesForPage(doc);
}
}
if (tmp.size() == 0) {
isEmpty = false;
getUserValuesForPage(doc);
}
}
// Unregister the existing listener, if any.
if (registrations.containsKey(url)) registrations.remove(url);
registrations.put(url, registration);
if (isEmpty) {
mActionBar.setBackgroundDrawable(new ColorDrawable(defaultColor));
color_map.put(url, defaultColor);
pageItemList.clear();
itemArrayAdapter.notifyDataSetChanged();
spinner.setVisibility(View.INVISIBLE);
} else {
if (blacklistArray.contains(extractDomain(url))) {
mActionBar.setBackgroundDrawable(new ColorDrawable(redToolbarColor));
showScamWarning(url);
retrieved_comments_dialog.show();
} else {
// If the current page is not a search page and not a tap on the search bar, show the prompt and the green header.
if (!url.contains(SEARCH_PARAM)) {
mActionBar.setBackgroundDrawable(new ColorDrawable(greenToolbarColor));
color_map.put(url, greenToolbarColor);
} else {
mActionBar.setBackgroundDrawable(new ColorDrawable(defaultColor));
color_map.put(url, defaultColor);
pageItemList.clear();
itemArrayAdapter.notifyDataSetChanged();
}
}
}
}
});
}
getUserValuesForPage():
private void getUserValuesForPage(DocumentSnapshot doc) {
DocumentReference mOtherUserDocRef = db.collection(USERS).document((String)doc.get(FSUSERID));
docRefList.add(doc);
mOtherUserDocRef.get(Source.SERVER).addOnCompleteListener((OnCompleteListener<DocumentSnapshot>) task -> {
// mUserDocRef.get(Source.SERVER).addOnCompleteListener((OnCompleteListener<DocumentSnapshot>) task -> {
if (task.isSuccessful()) {
DocumentSnapshot userDoc = task.getResult();
showComment(pageItemList, itemArrayAdapter,(String)doc.getId(), (String)doc.get(FSUSERID), (String)doc.get(FSCOMMENT), (String)doc.get(FSPATH), (HashMap<String, String>)doc.get(FSSEARCH), (String)doc.get(FSSUBJECT), (Timestamp) doc.get(FSTIMESTAMP), (String)doc.get(FSURL), false, (String)userDoc.get(FSDEVICEID), (String)userDoc.get(FSNAME), (String)userDoc.get(FSPICTUREURL), (String)doc.get(FSREPLY));
} else {
Toast.makeText(context, getString(R.string.getuser_error) + BLANK + Objects.requireNonNull(task.getException()).getMessage(), Toast.LENGTH_LONG);
crashlytics.log(context.getString(R.string.getuser_error) + BLANK + Objects.requireNonNull(task.getException()).getMessage());
crashlytics.log("User ID: " + doc.get(FSUSERID));
}
});
}
显示评论():
private void showComment(ArrayList<UserComments> itemList,
RecyclerView.Adapter adapter, String docID, String uid, String comment,
String path, HashMap<String, String> search, String subject, Timestamp
timestamp, String url, boolean scam_warning, String devid, String uname,
String photoURL, String reply ) {
UserComments nextComment = new UserComments();
nextComment.user_name = (uname != null ? uname :
getString(R.string.anon_person));
nextComment.device_id = devid;
nextComment.picture = (photoURL != null ? photoURL : SILHOUETTE_URL);
nextComment.timestamp = timestamp;
nextComment.subject = subject;
nextComment.docId = docID;
nextComment.reply = reply;
nextComment.userId = uid;
nextComment.comment = comment;
nextComment.site = extractSite(url);
nextComment.page_url = url;
nextComment.scam_warning = scam_warning;
nextComment.path = path;
nextComment.search = search;
if (!commentsStack.contains(nextComment)) commentsStack.add(nextComment);
itemList.add(commentsStack.pop());
if (showList) {
if (!recentCommentsShown) {
recentCommentsSpinner.setVisibility(View.VISIBLE);
return_to_list.setVisibility(View.INVISIBLE);
recent_comments_dialog.show();
}
recentCommentsShown = true;
showList = false;
}
Collections.sort(itemList, new SortByTime().reversed());
adapter.notifyDataSetChanged();
spinner.setVisibility(View.INVISIBLE);
recentCommentsSpinner.setVisibility(View.INVISIBLE);
}
UserComments.java:
public class UserComments {
Timestamp timestamp;
String hostname;
String path;
String page_url;
boolean scam_warning;
String userUID;
String device_id;
String picture;
String docId;
String replyDocID;
String user_name;
String subject;
String reply;
String userId;
String comment;
String site;
Map search;
}
我创建一个AlertDialog如下:
private void createRetrievedCommentsDialog(ArrayList<UserComments> list) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
View dialoglayout = getLayoutInflater().inflate(R.layout.retrieved_comments, null);
retrievedCommentsSpinner = dialoglayout.findViewById(R.id.retrievedCommentsProgressBar);
RecyclerView view = dialoglayout.findViewById(R.id.user_view);
itemArrayAdapter = new CommentsAdapter(this, activity, list);
view.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
view.setAdapter(itemArrayAdapter);
builder
.setView(dialoglayout)
.setCancelable(false)
.setNeutralButton(context.getString(R.string.dismiss), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
retrieved_comments_dialog = builder.create();
spinner.setVisibility(View.INVISIBLE);
}
该应用程序使用布尔值 autoshowComments 来控制屏幕是否应垂直分割为两部分,一个显示 WebView,另一个显示显示一堆数据的 RecyclerView:当 autoshowComments 为 true 时,屏幕被分割并显示数据被展示。我面临的问题是,如果在应用程序启动时将布尔值设置为 true,则尽管屏幕按预期分割,但数据不会显示在 WebView 下方。此外,如果我以 autoshowComments false 启动应用程序,然后使用菜单项将其更改为 true,
public boolean onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.overlay_menu).setChecked(autoshowComments);
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.overlay_menu) {
ViewGroup.LayoutParams params = browser_page.getLayoutParams();
if (item.isChecked()) {
item.setChecked(false);
user_view.setVisibility(View.GONE);
params.height = metrics.heightPixels;
browser_page.setLayoutParams(params);
autoshowComments = false;
} else {
item.setChecked(true);
user_view.setVisibility(View.VISIBLE);
params.height = Integer.valueOf((int) (WEBVIEW_HT * metrics.heightPixels));
browser_page.setLayoutParams(params);
autoshowComments = true;
}
updateAutoshow(autoshowComments);
return true;
}
}
数据项确实出现了(尽管它们没有像 fetchComments() 那样实时更新):
这是当应用程序启动且 autoshowComments 设置为 true 时屏幕的样子(“此页面的评论”下方不显示任何内容):
取消选中该框会出现以下情况(请注意,WebView 未调整大小):
当应用程序启动且 autoshowComments 设置为 false 时,我们得到:
取消选中该框后,页面将按预期调整大小。
点击绿色标题栏会显示 AlertDialog: 所以我的问题是为什么 pageItemList 在第一种情况下没有加载,但在第二种情况下加载?
我认为你的问题在这里:
pageItemList.clear();
itemArrayAdapter.notifyDataSetChanged();
在调用 notifyDataSetChanged 之前,pageItemList 需要数据。当我在代码中搜索 pageItemList 时,我没有看到任何将项目添加到 pageItemList 中的行。
检查这一点