- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Leak Canary 显示我的 Activity 有泄漏,但我不明白泄漏的原因。
我试图从 Activity 中移除零件以检查泄漏的来源,但没有奏效。我还从 Activity 中删除了所有内容,但仍然得到相同的结果。经过这些测试和许多其他测试后,我假设将我发送到 PostDetailActivity
的 Activity 有问题;还是我错了?
我是新手。对 Activity 的实现方式感到抱歉。
public class PostDetailActivity extends AppCompatActivity {
//details of user and post
String myUid, myName, myProfilPic, postId, pLikes, pDislike, pTitle, pTime, pImage, pUserPic, pUserName;
private DatabaseReference likesRef;
private DatabaseReference dislikeRef;
boolean mProcessLike = false;
boolean mProcessDislike = false;
Integer position, dislike, like;
//post views
ImageView userPicture, postImage;
TextView userName, postTime, postTitle;
Button likeBtn, dislikeBtn, shareBtn;
LinearLayout profileLayout, emptyRecycler, commentExtraSpace;
public RecyclerView recyclerView;
NestedScrollView scrollView;
public static List<Comment> commentList;
CommentAdapter commentAdapter;
//add comments views;
EditText commentEt;
ImageButton sendCommentBtn;
ImageView userCommentImage;
Comment replyComment;
@Override
protected void onCreate(Bundle savedInstanceState) {
// DARK/LIGHT THEME CODE START
if (DarkThem) {
setTheme(R.style.DarkTheme);
} else {
setTheme(R.style.LightTheme);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_post_detail);
myUid = FirebaseAuth.getInstance().getCurrentUser().getUid();
likesRef = FirebaseDatabase.getInstance().getReference().child("Likes");
dislikeRef = FirebaseDatabase.getInstance().getReference().child("Dislikes");
Toolbar toolbar = findViewById(R.id.toolBar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PostFragment.relogPost(position);
onBackPressed();
}
});
//getting post info with intent
Intent intent = getIntent();
postId = intent.getStringExtra("postId");
pLikes = intent.getStringExtra("pUp");
pDislike = intent.getStringExtra("pDown");
pTitle = intent.getStringExtra("pTitle");
pTime = intent.getStringExtra("pTime");
pImage = intent.getStringExtra("pImage");
pUserPic = intent.getStringExtra("uDp");
pUserName = intent.getStringExtra("uName");
try {
String positionList = intent.getStringExtra("position");
position = Integer.parseInt(positionList);
} catch (Exception e) {
}
//initializing views post
userPicture = findViewById(R.id.userPic);
postImage = findViewById(R.id.pImage);
userName = findViewById(R.id.userNamePost);
postTime = findViewById(R.id.pTime);
postTitle = findViewById(R.id.pTitle);
likeBtn = findViewById(R.id.upBtn);
dislikeBtn = findViewById(R.id.dwnBtn);
shareBtn = findViewById(R.id.shareBtn);
profileLayout = findViewById(R.id.profileLayout);
recyclerView = findViewById(R.id.recyclerView);
scrollView = findViewById(R.id.scrollView);
emptyRecycler = findViewById(R.id.emptyRecycler);
commentExtraSpace = findViewById(R.id.commentExtraSpace);
//initializing views comment
commentEt = findViewById(R.id.commentEt);
sendCommentBtn = findViewById(R.id.sendComment);
userCommentImage = findViewById(R.id.userCommentImage);
//convert time to dd//mm//yyyy hh:mm am/pm
Calendar calendar = Calendar.getInstance(Locale.getDefault());
calendar.setTimeInMillis(Long.parseLong(pTime));
String pTimeshown = DateFormat.format("dd/MM/yyyy hh:mm aa", calendar).toString();
//set data for PostDetails
userName.setText(pUserName);
postTime.setText(pTimeshown);
postTitle.setText(pTitle);
likeBtn.setText(pLikes);
dislikeBtn.setText(pDislike);
//Set user pic
if (pUserPic.equals("default")) {
userPicture.setImageResource(R.mipmap.ic_launcher_round);
} else {
try {
Glide.with(this).load(pUserPic).into(userPicture);
} catch (Exception e) {
}
}
//Setting postPicture
if (pImage.equals("default")) {
postImage.setImageResource(R.drawable.sunset);
} else {
try {
Glide.with(this).load(pImage).into(postImage);
} catch (Exception e) {
}
}
setLikes(postId);
setDislike(postId);
loadComments();
sendCommentBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendComment();
commentList.add(replyComment);
commentAdapter.notifyDataSetChanged();
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.scrollTo(0, recyclerView.getBottom());
}
});
}
});
dislikeBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pDislike = dislikeBtn.getText().toString();
pLikes = likeBtn.getText().toString();
mProcessDislike = true;
dislikeRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (mProcessDislike) {
if (dataSnapshot.child(postId).hasChild(myUid)) {
//already disliked ,so remove dislike
dislikeRef.child(postId).child(myUid).removeValue();
mProcessDislike = false;
dislikeBtn.setText(MessageFormat.format("{0}", Integer.parseInt(pDislike) - 1));
postList.get(position).setpDown("" + (Integer.parseInt(pDislike) - 1));
dislike = Integer.parseInt(pDislike) - 1;
postList.get(position).setpDown("" + dislike);
dislikeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_downvote_black, 0, 0, 0);
} else {
//not liked
likesRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
//verifying is user has liked the post
if (dataSnapshot.child(postId).hasChild(myUid)) {
likesRef.child(postId).child(myUid).removeValue();
dislikeRef.child(postId).child(myUid).setValue("-1");
likeBtn.setText(MessageFormat.format("{0}", Integer.parseInt(pLikes) - 1));
postList.get(position).setpUp("" + (Integer.parseInt(pLikes) - 1));
dislike = Integer.parseInt(pDislike) + 1;
dislikeBtn.setText(MessageFormat.format("{0}", dislike));
postList.get(position).setpDown("" + dislike);
} else {
dislikeRef.child(postId).child(myUid).setValue("-1");
dislike = Integer.parseInt(pDislike) + 1;
dislikeBtn.setText(MessageFormat.format("{0}", dislike));
postList.get(position).setpDown("" + dislike);
}
mProcessDislike = false;
dislikeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_disliked, 0, 0, 0);
likeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_upvote_black, 0, 0, 0);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
});
likeBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pDislike = dislikeBtn.getText().toString();
pLikes = likeBtn.getText().toString();
mProcessLike = true;
likesRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (mProcessLike) {
if (dataSnapshot.child(postId).hasChild(myUid)) {
//already liked ,so remove like
likesRef.child(postId).child(myUid).removeValue();
like = Integer.parseInt(pLikes) - 1;
mProcessLike = false;
likeBtn.setText(MessageFormat.format("{0}", like));
postList.get(position).setpUp("" + like);
likeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_upvote_black, 0, 0, 0);
} else {
//not liked
dislikeRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
//verifying is user has dislkied the post
if (dataSnapshot.child(postId).hasChild(myUid)) {
dislikeRef.child(postId).child(myUid).removeValue();
likesRef.child(postId).child(myUid).setValue("1");
dislikeBtn.setText(MessageFormat.format("{0}", Integer.parseInt(pDislike) - 1));
postList.get(position).setpDown("" + (Integer.parseInt(pDislike) - 1));
like = Integer.parseInt(pLikes) + 1;
likeBtn.setText(MessageFormat.format("{0}", like));
postList.get(position).setpUp("" + like);
dislikeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_downvote_black, 0, 0, 0);
} else {
likesRef.child(postId).child(myUid).setValue("1");
like = Integer.parseInt(pLikes) + 1;
likeBtn.setText(MessageFormat.format("{0}", like));
postList.get(position).setpUp("" + like);
}
mProcessLike = false;
likeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_liked, 0, 0, 0);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
});
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.scrollTo(0, commentExtraSpace.getBottom());
}
});
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference().child("Users").child(myUid);
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
myProfilPic = "" + dataSnapshot.child("imageURL").getValue();
myName = "" + dataSnapshot.child("username").getValue();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void sendComment() {
String comment = commentEt.getText().toString().trim();
//checking if empty
if (TextUtils.isEmpty(comment)) {
Toast.makeText(this, getString(R.string.EmptyComment), Toast.LENGTH_SHORT).show();
return;
}
String timeStamp = String.valueOf(System.currentTimeMillis());
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Comments");
HashMap<String, String> hashMap = new HashMap<>();
//put info in hashmap
hashMap.put("commentId", timeStamp);
hashMap.put("comment", comment);
hashMap.put("timeStamp", timeStamp);
hashMap.put("userId", myUid);
hashMap.put("userPicture", myProfilPic);
hashMap.put("userName", myName);
hashMap.put("like", "0");
hashMap.put("dislike", "0");
hashMap.put("replies", "no");
hashMap.put("liked", "no");
hashMap.put("disliked", "no");
databaseReference.child(postId).child(timeStamp).setValue(hashMap);
replyComment = new Comment(timeStamp, comment, timeStamp, "noid", myProfilPic, myName, "0", "0", "no", "no", "no");
commentEt.setText("");
}
private void loadComments() {
//linear layout for recyclerView
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
//set layout to recyclerView
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(linearLayoutManager);
//init comments list
commentList = new ArrayList<>();
//path of the post,to get comments;
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Comments").child(postId);
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
commentList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Comment comment = snapshot.getValue(Comment.class);
if (snapshot.child("comments").getChildrenCount() >= 1) {
comment.setReplies("" + snapshot.child("comments").getChildrenCount());
} else {
comment.setReplies("no");
}
if (snapshot.child("likes").hasChild(myUid)) {
comment.setLiked("yes");
} else {
comment.setLiked("no");
}
if (snapshot.child("dislikes").hasChild(myUid)) {
comment.setDisliked("yes");
} else {
comment.setDisliked("no");
}
comment.setLike(String.valueOf(snapshot.child("likes").getChildrenCount()));
comment.setDislike(String.valueOf(snapshot.child("dislikes").getChildrenCount()));
commentList.add(comment);
//setup adapter
}
commentAdapter = new CommentAdapter(PostDetailActivity.this, commentList, postId);
//set adapter
if (commentAdapter.getItemCount() > 0) {
recyclerView.setAdapter(commentAdapter);
emptyRecycler.setVisibility(View.GONE);
} else {
recyclerView.setVisibility(View.GONE);
emptyRecycler.setVisibility(View.VISIBLE);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void setLikes(final String postKey) {
likesRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.child(postKey).hasChild(myUid)) {
//user has liked this post
//indicate it with new design
likeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_liked, 0, 0, 0);
} else {
//user has not liked
likeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_upvote_black, 0, 0, 0);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void setDislike(final String postKey) {
dislikeRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.child(postKey).hasChild(myUid)) {
//user has liked this post
//indicate it with new design
dislikeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_disliked, 0, 0, 0);
} else {
//user has not liked
dislikeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_downvote_black, 0, 0, 0);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return super.onSupportNavigateUp();
}
@Override
public void onBackPressed() {
// PostFragment.recyclerView.getAdapter().notifyItemChanged(position);
if (isTaskRoot() && getSupportFragmentManager().getBackStackEntryCount() == 0) {
finishAfterTransition();
} else {
super.onBackPressed();
}
}
}
当我按下后退按钮时,我得到这个:
┬───
│ GC Root: System class
│
├─ android.app.ActivityThread class
│ Leaking: NO (a class is never leaking)
│ ↓ static ActivityThread.sCurrentActivityThread
│ ~~~~~~~~~~~~~~~~~~~~~~
├─ android.app.ActivityThread instance
│ Leaking: UNKNOWN
│ ↓ ActivityThread.mNewActivities
│ ~~~~~~~~~~~~~~
├─ android.app.ActivityThread$ActivityClientRecord instance
│ Leaking: UNKNOWN
│ ↓ ActivityThread$ActivityClientRecord.nextIdle
│ ~~~~~~~~
├─ android.app.ActivityThread$ActivityClientRecord instance
│ Leaking: UNKNOWN
│ ↓ ActivityThread$ActivityClientRecord.activity
│ ~~~~~~~~
╰→ com.RLD.newmemechat.PostDetailActivity instance
Leaking: YES (ObjectWatcher was watching this because com.RLD.newmemechat.PostDetailActivity received Activity#onDestroy() callback and Activity#mDestroyed is true)
key = 533b7987-0f38-41f4-9f1a-e468dcf83264
watchDurationMillis = 8537
retainedDurationMillis = 3530~~~
最佳答案
这明显是Android框架造成的漏洞。 leaktrace 中没有任何内容与您的代码有关,据我所知,ActivityThread 在 ActivityThread.mNewActivities 中维护着 ActivityThread$ActivityClientRecord 的链表。
你可以在这里看到:
// List of new activities (via ActivityRecord.nextIdle) that should
// be reported when next we idle.
ActivityClientRecord mNewActivities = null;
看起来这是由 ActivityThread.Idler 完成的,它在主线程空闲时运行:
private class Idler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
ActivityClientRecord a = mNewActivities;
boolean stopProfiling = false;
if (mBoundApplication != null && mProfiler.profileFd != null
&& mProfiler.autoStopProfiler) {
stopProfiling = true;
}
if (a != null) {
mNewActivities = null;
IActivityTaskManager am = ActivityTaskManager.getService();
ActivityClientRecord prev;
do {
if (localLOGV) Slog.v(
TAG, "Reporting idle of " + a +
" finished=" +
(a.activity != null && a.activity.mFinished));
if (a.activity != null && !a.activity.mFinished) {
try {
am.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
prev = a;
a = a.nextIdle;
prev.nextIdle = null;
} while (a != null);
}
if (stopProfiling) {
mProfiler.stopProfiling();
}
applyPendingProcessState();
return false;
}
}
这用于在创建 Activity 后主线程空闲时通知 Activity 管理器。不幸的是,如果主线程在 Activity.onCreate() 和 Activity.onDestroy() 之间没有空闲,这似乎会导致泄漏。
关于android - 修复由 Leak Canary 发现的 Activity 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62848503/
有谁知道蓝牙设备如何获取范围内可发现设备的设备 ID? 理想情况下,我正在寻找涉及蓝牙协议(protocol)最小实现的最简单解决方案。 一个起点会很好,我只是想创建一个设备,它可以以最小的功耗存储附
我有用于搜索Kibana中特定事件的查询,该查询与其他搜索一起保存,是否可以通过REST调用以编程方式更改它? 最佳答案 正如@Mohammad所说,所有与Kibana相关的元数据都存储在elasti
我正在使用带有这些注释的基本集成测试: @ExtendWith(SpringExtension::class) @SpringBootTest(classes = [SomeApplication::
以下是我的代码 HTML: Hello !! Javascript: $(function() { $('#content .child').click(function() {
我试图避免在每个 GDB session 中输入相同的命令。为此,我遵循了 rust discovery book 中的说明。但是当我通过 cargo run 运行程序时,程序没有像书中提到的那样工作
好的,我记得有一些命令可以放在 settings.py 文件中,这样基本上当您将 django 项目移动到另一个目录时,它就不会启动 foo-bar . 我知道我可以通过在它提到主目录的任何地方设置一
假设我正在制作一份注册表单。现在我希望它突出显示四个字段中的空白字段。现在我可以只执行一堆 if-else 语句,但这将花费很长时间。 假设我有以下代码: Javascript: if($firstn
我试图理解 C++ 中 regex 的逻辑 std::string s ("Ni Ni Ni NI"); std::regex e ("(Ni)"); std::smatch sm; std::re
运行时: vim /tmp/blah :q echo $? 我的退出状态为 1 .这破坏了包括 Git 在内的各种东西。如果我在没有 vimrc 的情况下运行 vim: vim -u NONE /tm
我无法通过“查找”来查找旧文件。我将我的发现链接到一个声明中,所有其他部分都运行良好。这是我所拥有的精简版。它搜索 $path 的目录树,并为找到的每个项目创建仅包含换行符的单独临时文件:所有文件、超
我已经多次看到这个问题,但没有一个答案对我有用。 我的 DotNet Core 应用程序失败 编码: public static void Main(string[] args) {
已解决见编辑 2 你好, 我一直在编写一个 Perl 程序来处理本地(专有)程序的自动升级(对于我工作的公司)。 基本上,它通过 cron 运行,不幸的是有内存泄漏(或类似的东西)。问题是泄漏只发生在
在 icCube 中创建到 Oracle 数据库的连接时,“选择现有数据库表”返回一个空的表列表。 连接很好,我可以查询模式创建 SQL 查询。 最佳答案 用户用作模式名称,但 Oracle 使用大写
我正在使用 VBA 循环遍历两个工作表上的行,如果它们匹配,则将工作表 2 中的行复制到工作表 1 中。 我的代码应该: 打开第二个工作簿 将所有信息复制到新工作表上的原始工作簿中 然后循环遍历原始工
当我尝试同步我的数据库时出现这个奇怪的错误: Unhandled rejection Error: Cyclic dependency found. roles is dependent of its
以编程方式发现 perl 模块具有的所有子例程的最佳方法是什么?这可以是一个模块、一个类(没有@EXPORT)或任何介于两者之间的东西。 编辑:下面的所有方法看起来都可以工作。我可能会在生产中使用 C
如何在“讨论”按钮左侧添加“共享”按钮。我希望该按钮与当前的“讨论”按钮具有相同的样式/颜色。 我从https://atmospherejs.com/joshowens/shareit添加了包 我将
我最近从 Netbeans 切换到 Eclipse,Eclipse 在我的项目中发现了许多 Netbeans 没有的语法错误,我不知道为什么。据可以看出,两个 IDE 都设置为使用 java 1.6。
我必须为我的项目设置一些不接受错误网址的规则。我为此使用正则表达式。 我的网址是“http://some/resource/location”。 此网址的开头、中间或结尾不应留有空格。 例如,这些空格
问题:鉴于作为 VMSS 的一部分启动的 N 个实例,我希望每个 Azure 实例上的应用程序代码能够发现其他对等实例的 IP 地址。我该怎么做? 总体目的是对实例进行集群,以提供主动被动 HA 或保
我是一名优秀的程序员,十分优秀!