我正在构建一个聊天应用程序,我有一个关于我的 fragment 的问题,该 fragment 包含一个包含所有聊天的 ListView 。
当用户收到一条消息时,聊天列表会更新(显示每次聊天的最后一条消息)(图片 1)。
当聊天不可见并且在该聊天中收到消息时,用户将收到通知(图片 2)
此时问题开始了。当用户单击通知时,聊天 ListView 似乎已损坏。当用户在点击通知后收到另一条消息时,他/她的手机会振动,但聊天 ListView 不会更改/更新。
其他 View 在点击通知后起作用。
下面是一段处理 ListView 更新的代码。
protected PacketListener packetListener = new PacketListener() {
@Override
public void processPacket(Packet packet) {
final Message message = (Message) packet;
if (message.getBody() != null) {
final String fromName = StringUtils.parseName(message.getFrom());
runOnUiThread(new Runnable(){
@Override
public void run() {
Boolean seen = false;
if(ChatFragment.currentChat != null && ChatFragment.currentChat.getContact().getUsername().equals(fromName) && VisibilityHelper.appIsVisible() && VisibilityHelper.fragmentIsVisible(ChatFragment.fragmentClassName)) {
seen = true;
}
Long chat_id = chatsDataSource.getChatByContactId(contactsDataSource.getContactByUsername(fromName).getId()).getId();
ChatMessage newChatMessage = chatMessagesDataSource.insertChatMessage(chat_id, ConstantHelper.CHAT_MESSAGES_TYPE_RECEIVED, seen, DateHelper.getDatetime(), message.getBody());
Log.d("DEBUG", VisibilityHelper.sCurrentFragmentClassName);
if(VisibilityHelper.appIsVisible() && VisibilityHelper.fragmentIsVisible(ChatsFragment.fragmentClassName)) {
ChatsFragment chatsFragment = (ChatsFragment) getFragmentManager().findFragmentByTag(ChatsFragment.fragmentClassName);
Log.d("DEBUG", "REFRESHING");
chatsFragment.refreshChatsList();
}
if(!VisibilityHelper.appIsVisible()) {
notificationHelper.externalNotification(getBaseContext(), newChatMessage);
} else {
if(ChatFragment.currentChat != null && ChatFragment.currentChat.getContact().getUsername().equals(fromName) && VisibilityHelper.appIsVisible() && VisibilityHelper.fragmentIsVisible(ChatFragment.fragmentClassName)) {
ChatFragment.chatsList.add(newChatMessage);
ChatFragment.chatsList.notifyDataSetChanged();
} else {
notificationHelper.internalNotification(getBaseContext(), newChatMessage);
}
}
}
});
}
}
};
主要 Activity (如何创建 fragment )
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_main);
Bundle extras = getIntent().getExtras();
initializeDataSources();
setLastContactUpdate();
if(usersDataSource.getCurrentUser() == null)
{
Intent LoginActivity = new Intent(getApplicationContext(), LoginActivity.class);
LoginActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(LoginActivity);
finish();
}
else
{
if(localServiceBinder == null)
localServiceBinder = new LocalServiceBinder();
bindLocalService();
runDispatchMethod(extras, savedInstanceState);
if (savedInstanceState == null) {
getAndSaveUserDetails();
GCMRegistrationID = registerGCM();
}
}
}
protected void runDispatchMethod(Bundle extras, Bundle savedInstanceState) {
if(savedInstanceState == null) {
startFragment(new ChatsFragment(), false);
}
if(extras != null && extras.getString(ConstantHelper.RECEIVED_MESSAGES_FROM) != null && !extras.getString(ConstantHelper.RECEIVED_MESSAGES_FROM).equals("")) {
getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
startFragment(new ChatsFragment(), false);
ChatFragment chatFragment = new ChatFragment();
Bundle chatExtras = (Bundle) new Bundle();
chatExtras.putString(ConstantHelper.RECEIVED_MESSAGES_FROM, extras.getString(ConstantHelper.RECEIVED_MESSAGES_FROM));
chatFragment.setArguments(chatExtras);
startFragment(chatFragment);
return;
}
}
public void startFragment(Fragment newFragment) {
startFragment(newFragment, true);
}
public void startFragment(Fragment newFragment, Boolean addToBackstack) {
if(addToBackstack) {
getFragmentManager().beginTransaction().replace(R.id.container, newFragment, newFragment.getClass().getName()).addToBackStack(newFragment.getClass().getName()).commit();
} else {
getFragmentManager().beginTransaction().replace(R.id.container, newFragment, newFragment.getClass().getName()).commit();
}
getFragmentManager().executePendingTransactions();
}
聊天适配器
public class ChatsAdapter extends BaseAdapter {
private List<Chat> chats;
private LayoutInflater inflater;
private String emptyLastMessageValue;
public ChatsAdapter(Context context, List<Chat> chats) {
this.chats = chats;
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
emptyLastMessageValue = context.getText(R.string.fragment_chats_chat_created).toString();
}
@Override
public int getCount() {
return chats.size();
}
@Override
public Chat getItem(int position) {
return chats.get(position);
}
@Override
public long getItemId(int position) {
return chats.get(position).getId();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View chatAdapterView = convertView;
if(convertView == null)
chatAdapterView = inflater.inflate(R.layout.adapter_chats, null);
TextView layout_fullname = (TextView) chatAdapterView.findViewById(R.id.fullname);
TextView layout_last_message = (TextView) chatAdapterView.findViewById(R.id.last_message);
TextView layout_unread_messages = (TextView) chatAdapterView.findViewById(R.id.unread_messages);
TextView layout_last_message_datetime = (TextView) chatAdapterView.findViewById(R.id.last_message_datetime);
Chat row = chats.get(position);
String firstname = row.getContact().getFirstname();
String fullname = row.getContact().getFullname();
if(firstname == null || firstname.equals(""))
fullname = StringHelper.ucfirst(row.getContact().getUsername());
layout_fullname.setText(fullname);
String last_message_value;
String last_message_datetime_value = "";
if(row.getLastMessage() == null) {
last_message_value = emptyLastMessageValue;
layout_last_message_datetime.setVisibility(TextView.GONE);
layout_unread_messages.setVisibility(TextView.GONE);
} else {
last_message_value = row.getLastMessage().getMessageBody();
last_message_datetime_value = DateHelper.toReadableDatetime(row.getLastMessage().getMessageDatetime());
layout_last_message_datetime.setText(last_message_datetime_value);
Integer unreadMessages = row.getUnreadMessages();
if(unreadMessages > 0) {
layout_unread_messages.setText(String.valueOf(unreadMessages));
layout_unread_messages.setVisibility(TextView.VISIBLE);
} else {
layout_unread_messages.setVisibility(TextView.GONE);
}
}
layout_last_message.setText(last_message_value);
return chatAdapterView;
}
}
刷新聊天列表功能
public void refreshChatsList() {
Log.d("DEBUG", "It does come here!");
chats.clear();
chats.addAll(((MainActivity) getActivity()).chatsDataSource.getAllChats());
chats_adapter.notifyDataSetChanged();
}
Logcat 输出
07-06 20:12:43.892: D/SMACK(14948): 08:12:43 PM RCV (1106735848): <message id="3jRRg-24" to="tijme@192.168.137.1" type="chat" from="test@192.168.137.1/Smack"><body>Test</body></message>
07-06 20:12:43.962: D/DEBUG(14948): nl.test.messatch.fragments.ChatsFragment
07-06 20:12:43.962: D/DEBUG(14948): REFRESHING
07-06 20:12:43.962: D/DEBUG(14948): It does come here!
07-06 20:12:48.406: D/SMACK(14948): 08:12:48 PM RCV (1106735848): <message id="3jRRg-25" to="tijme@192.168.137.1" type="chat" from="test@192.168.137.1/Smack"><body>Test 2</body></message>
07-06 20:12:48.446: D/DEBUG(14948): nl.test.messatch.fragments.ChatsFragment
07-06 20:12:51.059: D/KUTZOOI(14948): HELEMAAL WÄCK
07-06 20:12:51.099: D/dalvikvm(14948): GC_FOR_ALLOC freed 161K, 3% free 9653K/9912K, paused 19ms, total 21ms
07-06 20:12:51.109: I/dalvikvm-heap(14948): Grow heap (frag case) to 13.272MB for 4000016-byte allocation
07-06 20:12:51.139: D/dalvikvm(14948): GC_FOR_ALLOC freed 1K, 2% free 13558K/13820K, paused 25ms, total 25ms
07-06 20:12:54.953: D/SMACK(14948): 08:12:54 PM RCV (1106735848): <message id="3jRRg-26" to="tijme@192.168.137.1" type="chat" from="test@192.168.137.1/Smack"><body>Test 3</body></message>
07-06 20:12:54.993: D/DEBUG(14948): nl.test.messatch.fragments.ChatsFragment
07-06 20:12:54.993: D/DEBUG(14948): REFRESHING
07-06 20:12:54.993: D/DEBUG(14948): It does come here!
聊天列表
通知
最佳答案
确保您在通过单击通知返回 Activity 后使用相同的 fragment (根据问题出现的方式判断)。如果您不持有对用户看到的同一实例的引用,那么任何聊天更新都将无提示地失败,因为您将只更新背景 fragment (而不是可见 fragment )。错误似乎出现在 runDispatchMethod() 中,您每次都在其中使用新 fragment 进行交易,而不是检查 ChatsFragment 的另一个实例是否已经可用(在这种情况下您只需在该实例上调用更新方法即可)。
关于java - 打开通知后 fragment 不会更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24598719/
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht