/* * Copyright 2017 GcsSloop * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Last modified 2017-03-08 04:22:13 * * GitHub: https://github.com/GcsSloop * Website: http://www.gcssloop.com * Weibo: http://weibo.com/GcsSloop */ package com.gcssloop.diycode.activity; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import android.widget.FrameLayout; import com.gcssloop.diycode.R; import com.gcssloop.diycode.adapter.TopicReplyAdapter; import com.gcssloop.diycode.base.app.BaseActivity; import com.gcssloop.diycode.base.app.ViewHolder; import com.gcssloop.diycode.base.webview.GcsMarkdownViewClient; import com.gcssloop.diycode.base.webview.WebImageListener; import com.gcssloop.diycode.utils.DataCache; import com.gcssloop.diycode.utils.NetUtil; import com.gcssloop.diycode.utils.RecyclerViewUtil; import com.gcssloop.diycode.widget.MarkdownView; import com.gcssloop.diycode_sdk.api.topic.bean.Topic; import com.gcssloop.diycode_sdk.api.topic.bean.TopicContent; import com.gcssloop.diycode_sdk.api.topic.bean.TopicReply; import com.gcssloop.diycode_sdk.api.topic.event.CreateTopicReplyEvent; import com.gcssloop.diycode_sdk.api.topic.event.GetTopicEvent; import com.gcssloop.diycode_sdk.api.topic.event.GetTopicRepliesListEvent; import com.gcssloop.diycode_sdk.api.user.bean.User; import com.gcssloop.diycode_sdk.log.Logger; import com.gcssloop.diycode.utils.TimeUtil; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.util.List; public class TopicContentActivity extends BaseActivity implements View.OnClickListener { public static String TOPIC = "topic"; public static String TOPIC_ID = "topic_id"; public static String ERROR = "error"; public static String TYPE = "type"; private int topic_id = -1; private Topic topic = null; private DataCache mDataCache; private TopicReplyAdapter mAdapter; private MarkdownView mMarkdownView; private GcsMarkdownViewClient mWebViewClient; private EditText myReply; public static void newInstance(@NonNull Context context, @NonNull Topic topic) { Intent intent = new Intent(context, TopicContentActivity.class); intent.putExtra(TOPIC, topic); context.startActivity(intent); } public static void newInstance(@NonNull Context context, @NonNull int topic_id) { Intent intent = new Intent(context, TopicContentActivity.class); intent.putExtra(TOPIC_ID, topic_id); context.startActivity(intent); } @Override protected int getLayoutId() { return R.layout.activity_topic_content; } // 初始化数据 @Override protected void initDatas() { Intent intent = getIntent(); topic_id = intent.getIntExtra(TOPIC_ID, -1); topic = (Topic) intent.getSerializableExtra(TOPIC); if (topic != null && topic_id <= 0) { topic_id = topic.getId(); } } @Override protected void initViews(ViewHolder holder, View root) { setTitle("话题"); mDataCache = new DataCache(this); initRecyclerView(holder); initMarkdownView(holder); loadData(holder); } private void initRecyclerView(ViewHolder holder) { mAdapter = new TopicReplyAdapter(this); RecyclerView recyclerView = holder.get(R.id.reply_list); RecyclerViewUtil.init(this, recyclerView, mAdapter); } private void initMarkdownView(ViewHolder holder) { FrameLayout layout = holder.get(R.id.webview_container); mMarkdownView = new MarkdownView(this.getApplicationContext()); mMarkdownView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); layout.addView(mMarkdownView); WebImageListener listener = new WebImageListener(this, ImageActivity.class); mMarkdownView.addJavascriptInterface(listener, "listener"); mWebViewClient = new GcsMarkdownViewClient(this); mMarkdownView.setWebViewClient(mWebViewClient); } // 在 start 和 restart 调用 private void initReply(ViewHolder holder) { if (!mDiycode.isLogin()) { holder.get(R.id.need_login).setVisibility(View.VISIBLE); holder.get(R.id.can_reply).setVisibility(View.GONE); holder.setOnClickListener(this, R.id.login); } else { holder.get(R.id.need_login).setVisibility(View.GONE); holder.get(R.id.can_reply).setVisibility(View.VISIBLE); holder.setOnClickListener(this, R.id.send_reply); myReply = holder.get(R.id.my_reply); } } // 初始化 topic 内容面板的数据 @SuppressLint({"AddJavascriptInterface", "JavascriptInterface"}) private void loadData(ViewHolder holder) { if (null != topic) { showPreview(topic); if (shouldReloadTopic(topic)) { mDiycode.getTopic(topic.getId()); mDiycode.getTopicRepliesList(topic.getId(), null, topic.getReplies_count()); } else { loadCache(); } } else if (topic_id > 0) { // 若是缓存有内容则读取缓存 TopicContent temp = mDataCache.getTopicContent(topic_id); if (temp != null) { showPreview(temp); } mDiycode.getTopic(topic_id); mDiycode.getTopicRepliesList(topic_id, null, 100); } else { toastShort("参数传递错误"); } } private void loadCache() { TopicContent topicContent = mDataCache.getTopicContent(topic.getId()); if (null != topicContent) { Logger.i("数据不变 - 来自缓存"); mMarkdownView.setMarkDownText(topicContent.getBody()); } else { mDiycode.getTopic(topic.getId()); } List<TopicReply> replies = mDataCache.getTopicRepliesList(topic.getId()); if (null != replies) { Logger.i("回复不变 - 来自缓存"); mAdapter.addDatas(replies); } else { mDiycode.getTopicRepliesList(topic.getId(), null, topic.getReplies_count()); } } // 是否需重新加载 topic 详情 private boolean shouldReloadTopic(@NonNull Topic topic) { if (!NetUtil.isNetConnection(this)) { return false; // 无网络,无法加载 } if (null == mDataCache.getTopicContent(topic.getId())) { return true; // 无缓存,需要加载 } TopicContent content = mDataCache.getTopicContent(topic.getId()); if (!content.getUpdated_at().equals(topic.getUpdated_at())) { return true; // 更新时间不同,需要加载 } return false; } // 显示基础数据 private void showPreview(Topic topic) { ViewHolder holder = getViewHolder(); User user = topic.getUser(); holder.setText(R.id.username, user.getLogin() + "(" + user.getName() + ")"); holder.setText(R.id.time, TimeUtil.computePastTime(topic.getUpdated_at())); holder.setText(R.id.title, topic.getTitle()); holder.setText(R.id.reply_count, "共收到 " + topic.getReplies_count() + "条回复"); holder.loadImage(this, user.getAvatar_url(), R.id.avatar); holder.setOnClickListener(this, R.id.avatar, R.id.username); } // 显示基础数据 private void showPreview(TopicContent topic) { ViewHolder holder = getViewHolder(); User user = topic.getUser(); holder.setText(R.id.username, user.getLogin() + "(" + user.getName() + ")"); holder.setText(R.id.time, TimeUtil.computePastTime(topic.getUpdated_at())); holder.setText(R.id.title, topic.getTitle()); holder.setText(R.id.reply_count, "共收到 " + topic.getReplies_count() + "条回复"); holder.loadImage(this, user.getAvatar_url(), R.id.avatar); holder.setOnClickListener(this, R.id.avatar, R.id.username); } // 显示全部数据 private void showAll(TopicContent topic) { showPreview(topic); mMarkdownView.setMarkDownText(topic.getBody()); } @Subscribe(threadMode = ThreadMode.MAIN) public void onTopicDetail(GetTopicEvent event) { if (event.isOk()) { showAll(event.getBean()); mDataCache.saveTopicContent(event.getBean()); } } @Subscribe(threadMode = ThreadMode.MAIN) public void onTopicRepliesList(GetTopicRepliesListEvent event) { if (event.isOk()) { Logger.i("topic reply 回复 - 来自网络"); mAdapter.clearDatas(); mAdapter.addDatas(event.getBean()); mDataCache.saveTopicRepliesList(topic_id, event.getBean()); } else { // toastShort("获取回复失败"); } } @Subscribe(threadMode = ThreadMode.MAIN) public void onCreateReply(CreateTopicReplyEvent event) { if (event.isOk()) { Logger.i("回复成功"); myReply.setText(""); mDiycode.getTopicRepliesList(topic.getId(), null, topic.getReplies_count() + 1); } else { toastShort("回复失败"); } } // 防止 WebView 引起的内存泄漏 public void clearWebViewResource() { if (mMarkdownView != null) { mMarkdownView.clearHistory(); ((ViewGroup) mMarkdownView.getParent()).removeView(mMarkdownView); mMarkdownView.setTag(null); mMarkdownView.loadUrl("about:blank"); mMarkdownView.stopLoading(); mMarkdownView.setWebViewClient(null); mMarkdownView.setWebChromeClient(null); mMarkdownView.removeAllViews(); mMarkdownView.destroy(); mMarkdownView = null; } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { finish(); return true; } return super.onKeyDown(keyCode, event); } @Override protected void onStart() { super.onStart(); EventBus.getDefault().register(this); initReply(getViewHolder()); } @Override protected void onRestart() { super.onRestart(); initReply(getViewHolder()); } @Override protected void onStop() { super.onStop(); EventBus.getDefault().unregister(this); } @Override protected void onDestroy() { super.onDestroy(); clearWebViewResource(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.avatar: case R.id.username: if (null != topic) { openActivity(UserActivity.class, UserActivity.USER, topic.getUser()); } break; case R.id.login: openActivity(LoginActivity.class); break; case R.id.send_reply: String reply = myReply.getText().toString(); if (reply.isEmpty()) { toastShort("评论内容不能为空。"); return; } mDiycode.createTopicReply(topic.getId(), reply); break; } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.topic_content, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_share: String mUrl = "https://www.diycode.cc/topics/" + topic.getId(); Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.putExtra(Intent.EXTRA_SUBJECT, topic.getTitle()); shareIntent.putExtra(Intent.EXTRA_TEXT, mUrl); shareIntent.setType("text/plain"); startActivity(shareIntent); break; } return super.onOptionsItemSelected(item); } }