fixed NPE

This commit is contained in:
Mariotaku Lee 2017-04-14 23:03:58 +08:00
parent 92c70380b9
commit 4ca03254ec
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
6 changed files with 220 additions and 252 deletions

View File

@ -1,237 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.LruCache;
import org.mariotaku.microblog.library.twitter.model.User;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.ParcelableUserList;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.util.UserKeyUtils;
import java.util.Map;
import java.util.Set;
import static android.text.TextUtils.isEmpty;
import static org.mariotaku.twidere.TwidereConstants.USER_COLOR_PREFERENCES_NAME;
import static org.mariotaku.twidere.TwidereConstants.USER_NICKNAME_PREFERENCES_NAME;
public class UserColorNameManager {
private final static String NICKNAME_NULL = ".#NULL#";
private final SharedPreferences colorPreferences, nicknamePreferences;
private final LruCache<String, Integer> colorCache;
private final LruCache<String, String> nicknameCache;
public UserColorNameManager(Context context) {
colorPreferences = context.getSharedPreferences(USER_COLOR_PREFERENCES_NAME, Context.MODE_PRIVATE);
nicknamePreferences = context.getSharedPreferences(USER_NICKNAME_PREFERENCES_NAME, Context.MODE_PRIVATE);
colorCache = new LruCache<>(512);
nicknameCache = new LruCache<>(256);
}
public SharedPreferences getColorPreferences() {
return colorPreferences;
}
public SharedPreferences getNicknamePreferences() {
return nicknamePreferences;
}
public static String decideDisplayName(final String nickname, final String name,
final String screenName, final boolean nameFirst) {
if (!isEmpty(nickname)) return nickname;
return nameFirst && !isEmpty(name) ? name : "@" + screenName;
}
public static String decideNickname(String nick, String name) {
return isEmpty(nick) ? name : nick;
}
public void registerColorChangedListener(final UserColorChangedListener listener) {
colorPreferences.registerOnSharedPreferenceChangeListener(new OnColorPreferenceChangeListener(listener));
}
public void registerNicknameChangedListener(final UserNicknameChangedListener listener) {
nicknamePreferences.registerOnSharedPreferenceChangeListener(new OnNickPreferenceChangeListener(listener));
}
public void clearUserColor(@NonNull final UserKey userKey) {
final SharedPreferences.Editor editor = colorPreferences.edit();
final String userKeyString = userKey.toString();
colorCache.remove(userKeyString);
editor.remove(userKeyString);
editor.apply();
}
public void setUserColor(@NonNull final UserKey userKey, final int color) {
final SharedPreferences.Editor editor = colorPreferences.edit();
final String userKeyString = userKey.toString();
colorCache.put(userKeyString, color);
editor.putInt(userKeyString, color);
editor.apply();
}
public void setUserNickname(@NonNull final UserKey userKey, final String nickname) {
final SharedPreferences.Editor editor = nicknamePreferences.edit();
final String userKeyString = userKey.toString();
nicknameCache.put(userKeyString, nickname);
editor.putString(userKeyString, nickname);
editor.apply();
}
public void clearUserNickname(@NonNull final UserKey userKey) {
final SharedPreferences.Editor editor = nicknamePreferences.edit();
final String userKeyString = userKey.toString();
nicknameCache.remove(userKeyString);
editor.remove(userKeyString);
editor.apply();
}
public String getDisplayName(final ParcelableUser user, final boolean nameFirst) {
return getDisplayName(user.key, user.name, user.screen_name, nameFirst);
}
public String getDisplayName(final User user, final boolean nameFirst) {
return getDisplayName(UserKeyUtils.fromUser(user), user.getName(), user.getScreenName(), nameFirst);
}
public String getDisplayName(final ParcelableUserList user, final boolean nameFirst) {
return getDisplayName(user.user_key, user.user_name, user.user_screen_name, nameFirst);
}
public String getDisplayName(final ParcelableStatus status, final boolean nameFirst) {
return getDisplayName(status.user_key, status.user_name, status.user_screen_name, nameFirst);
}
public String getDisplayName(@NonNull final UserKey userKey, final String name,
final String screenName, final boolean nameFirst) {
return getDisplayName(userKey.toString(), name, screenName, nameFirst);
}
public String getDisplayName(@NonNull final String userId, final String name,
final String screenName, final boolean nameFirst) {
final String nick = getUserNicknameInternal(userId);
return decideDisplayName(nick, name, screenName, nameFirst);
}
public int getUserColor(@NonNull final UserKey userKey) {
return getUserColor(userKey.toString());
}
public int getUserColor(@NonNull final String userId) {
final Integer cached = colorCache.get(userId);
if (cached != null) return cached;
final int color = colorPreferences.getInt(userId, Color.TRANSPARENT);
colorCache.put(userId, color);
return color;
}
@Nullable
public String getUserNickname(@NonNull final UserKey userKey) {
final String userKeyString = userKey.toString();
return getUserNicknameInternal(userKeyString);
}
@Nullable
public String getUserNickname(@NonNull final UserKey userKey, final String name) {
final String nick = getUserNickname(userKey);
return decideNickname(nick, name);
}
@Nullable
public String getUserNickname(@NonNull final String userId, final String name) {
final String nick = getUserNicknameInternal(userId);
return decideNickname(nick, name);
}
public Set<? extends Map.Entry<String, ?>> getNameEntries() {
return nicknamePreferences.getAll().entrySet();
}
private String getUserNicknameInternal(@NonNull final String userId) {
final String cached = nicknameCache.get(userId);
if (NICKNAME_NULL.equals(cached)) return null;
if (cached != null) return cached;
final String nickname = nicknamePreferences.getString(userId, null);
if (nickname != null) {
nicknameCache.put(userId, nickname);
} else {
nicknameCache.put(userId, NICKNAME_NULL);
}
return nickname;
}
public interface UserColorChangedListener {
void onUserColorChanged(@NonNull UserKey userKey, int color);
}
public interface UserNicknameChangedListener {
void onUserNicknameChanged(@NonNull UserKey userKey, @Nullable String nick);
}
private static final class OnColorPreferenceChangeListener implements OnSharedPreferenceChangeListener {
private final UserColorChangedListener mListener;
OnColorPreferenceChangeListener(final UserColorChangedListener listener) {
mListener = listener;
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) {
final UserKey userKey = UserKey.valueOf(key);
if (mListener != null) {
mListener.onUserColorChanged(userKey, preferences.getInt(key, 0));
}
}
}
private static final class OnNickPreferenceChangeListener implements OnSharedPreferenceChangeListener {
private final UserNicknameChangedListener mListener;
OnNickPreferenceChangeListener(final UserNicknameChangedListener listener) {
mListener = listener;
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) {
final UserKey userKey = UserKey.valueOf(key);
if (mListener != null) {
mListener.onUserNicknameChanged(userKey, preferences.getString(key, null));
}
}
}
}

View File

@ -434,7 +434,7 @@ public final class Utils implements Constants {
public static String[] getMatchedNicknameKeys(final String str, UserColorNameManager manager) {
if (TextUtils.isEmpty(str)) return new String[0];
final List<String> list = new ArrayList<>();
for (final Entry<String, ?> entry : manager.getNameEntries()) {
for (final Entry<String, ?> entry : manager.getNicknames().entrySet()) {
final String value = ParseUtils.parseString(entry.getValue());
final String key = entry.getKey();
if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) {

View File

@ -24,8 +24,10 @@ import android.content.DialogInterface
import android.os.Bundle
import android.support.v4.app.FragmentManager
import android.support.v7.app.AlertDialog
import org.mariotaku.ktextension.Bundle
import org.mariotaku.ktextension.set
import org.mariotaku.twidere.R
import org.mariotaku.twidere.constant.IntentConstants
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_USER
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_NAME_FIRST
import org.mariotaku.twidere.extension.applyTheme
import org.mariotaku.twidere.model.ParcelableUser
@ -35,7 +37,6 @@ class DestroyFriendshipDialogFragment : BaseDialogFragment(), DialogInterface.On
override fun onClick(dialog: DialogInterface, which: Int) {
when (which) {
DialogInterface.BUTTON_POSITIVE -> {
val user = user ?: return
twitterWrapper.destroyFriendshipAsync(user.account_key, user.key)
}
else -> {
@ -59,22 +60,18 @@ class DestroyFriendshipDialogFragment : BaseDialogFragment(), DialogInterface.On
return dialog
}
private val user: ParcelableUser?
get() {
val args = arguments
if (!args.containsKey(IntentConstants.EXTRA_USER)) return null
return args.getParcelable<ParcelableUser>(IntentConstants.EXTRA_USER)
}
private val user: ParcelableUser
get() = arguments.getParcelable(EXTRA_USER)
companion object {
val FRAGMENT_TAG = "destroy_friendship"
fun show(fm: FragmentManager, user: ParcelableUser): DestroyFriendshipDialogFragment {
val args = Bundle()
args.putParcelable(IntentConstants.EXTRA_USER, user)
val f = DestroyFriendshipDialogFragment()
f.arguments = args
f.arguments = Bundle {
this[EXTRA_USER] = user
}
f.show(fm, FRAGMENT_TAG)
return f
}

View File

@ -654,8 +654,6 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val activity = activity
userColorNameManager.registerColorChangedListener(this)
userColorNameManager.registerNicknameChangedListener(this)
nameFirst = preferences.getBoolean(KEY_NAME_FIRST)
cardBackgroundColor = ThemeUtils.getCardBackgroundColor(activity,
preferences[themeBackgroundOptionKey], preferences[themeBackgroundAlphaKey])
@ -739,10 +737,14 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
override fun onStart() {
super.onStart()
bus.register(this)
userColorNameManager.registerColorChangedListener(this)
userColorNameManager.registerNicknameChangedListener(this)
}
override fun onStop() {
userColorNameManager.unregisterColorChangedListener(this)
userColorNameManager.unregisterNicknameChangedListener(this)
bus.unregister(this)
super.onStop()
}
@ -1385,6 +1387,7 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
} else {
taskColor = ColorUtils.setAlphaComponent(theme.colorToolbar, 0xFF)
}
val user = this.user
if (user != null) {
val name = userColorNameManager.getDisplayName(user, nameFirst)
ActivitySupport.setTaskDescription(activity, TaskDescriptionCompat(name, null, taskColor))

View File

@ -88,8 +88,8 @@ class UserListMembersFragment : CursorUsersListFragment() {
if (accountKey == null || accountKey != userKey) return
val inflater = MenuInflater(context)
val contextMenuInfo = menuInfo as ExtendedRecyclerView.ContextMenuInfo?
val user = adapter.getUser(contextMenuInfo!!.position) ?: return
inflater.inflate(R.menu.action_user_list_member, menu)
val user = adapter.getUser(contextMenuInfo!!.position)
menu.setHeaderTitle(userColorNameManager.getDisplayName(user, preferences[nameFirstKey]))
}

View File

@ -0,0 +1,205 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util
import android.content.Context
import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.graphics.Color
import android.support.v4.util.ArrayMap
import android.support.v4.util.LruCache
import org.mariotaku.microblog.library.twitter.model.User
import org.mariotaku.twidere.TwidereConstants.USER_COLOR_PREFERENCES_NAME
import org.mariotaku.twidere.TwidereConstants.USER_NICKNAME_PREFERENCES_NAME
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.ParcelableUserList
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.UserKeyUtils
class UserColorNameManager(context: Context) {
val colorPreferences: SharedPreferences = context.getSharedPreferences(USER_COLOR_PREFERENCES_NAME, Context.MODE_PRIVATE)
val nicknamePreferences: SharedPreferences = context.getSharedPreferences(USER_NICKNAME_PREFERENCES_NAME, Context.MODE_PRIVATE)
val nicknames: Map<String, Any?>
get() = nicknamePreferences.all
private val colorCache = LruCache<String, Int>(512)
private val nicknameCache = LruCache<String, String>(256)
private val colorChangedListeners = ArrayMap<UserColorChangedListener, OnSharedPreferenceChangeListener>()
private val nicknameChangedListeners = ArrayMap<UserNicknameChangedListener, OnSharedPreferenceChangeListener>()
fun clearUserColor(userKey: UserKey) {
val editor = colorPreferences.edit()
val userKeyString = userKey.toString()
colorCache.remove(userKeyString)
editor.remove(userKeyString)
editor.apply()
}
fun setUserColor(userKey: UserKey, color: Int) {
val editor = colorPreferences.edit()
val userKeyString = userKey.toString()
colorCache.put(userKeyString, color)
editor.putInt(userKeyString, color)
editor.apply()
}
fun setUserNickname(userKey: UserKey, nickname: String) {
val editor = nicknamePreferences.edit()
val userKeyString = userKey.toString()
nicknameCache.put(userKeyString, nickname)
editor.putString(userKeyString, nickname)
editor.apply()
}
fun clearUserNickname(userKey: UserKey) {
val editor = nicknamePreferences.edit()
val userKeyString = userKey.toString()
nicknameCache.remove(userKeyString)
editor.remove(userKeyString)
editor.apply()
}
fun getDisplayName(user: ParcelableUser, nameFirst: Boolean): String {
return getDisplayName(user.key, user.name, user.screen_name, nameFirst)
}
fun getDisplayName(user: User, nameFirst: Boolean): String {
return getDisplayName(UserKeyUtils.fromUser(user), user.name, user.screenName, nameFirst)
}
fun getDisplayName(user: ParcelableUserList, nameFirst: Boolean): String {
return getDisplayName(user.user_key, user.user_name, user.user_screen_name, nameFirst)
}
fun getDisplayName(status: ParcelableStatus, nameFirst: Boolean): String {
return getDisplayName(status.user_key, status.user_name, status.user_screen_name, nameFirst)
}
fun getDisplayName(userKey: UserKey, name: String, screenName: String, nameFirst: Boolean): String {
return getDisplayName(userKey.toString(), name, screenName, nameFirst)
}
fun getDisplayName(key: String, name: String, screenName: String, nameFirst: Boolean): String {
val nick = getUserNicknameInternal(key)
return decideDisplayName(nick, name, screenName, nameFirst)
}
fun getUserColor(userKey: UserKey): Int {
return getUserColor(userKey.toString())
}
fun getUserColor(userId: String): Int {
val cached = colorCache.get(userId)
if (cached != null) return cached
val color = colorPreferences.getInt(userId, Color.TRANSPARENT)
colorCache.put(userId, color)
return color
}
fun getUserNickname(userKey: UserKey): String? {
val userKeyString = userKey.toString()
return getUserNicknameInternal(userKeyString)
}
fun getUserNickname(userKey: UserKey, name: String): String? {
val nick = getUserNickname(userKey)
return decideNickname(nick, name)
}
fun getUserNickname(key: String, name: String): String? {
val nick = getUserNicknameInternal(key)
return decideNickname(nick, name)
}
fun registerColorChangedListener(listener: UserColorChangedListener) {
val preferenceChangeListener = OnColorPreferenceChangeListener(listener)
colorPreferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
colorChangedListeners[listener] = preferenceChangeListener
}
fun registerNicknameChangedListener(listener: UserNicknameChangedListener) {
val preferenceChangeListener = OnNickPreferenceChangeListener(listener)
nicknamePreferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
nicknameChangedListeners[listener] = preferenceChangeListener
}
fun unregisterColorChangedListener(listener: UserColorChangedListener) {
val preferenceChangeListener = colorChangedListeners[listener] ?: return
colorPreferences.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener)
}
fun unregisterNicknameChangedListener(listener: UserNicknameChangedListener) {
val preferenceChangeListener = nicknameChangedListeners[listener] ?: return
nicknamePreferences.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener)
}
private fun getUserNicknameInternal(key: String): String? {
val cached = nicknameCache.get(key)
if (NICKNAME_NULL == cached) return null
if (cached != null) return cached
val nickname = nicknamePreferences.getString(key, null)?.takeIf(String::isNotEmpty)
if (nickname != null) {
nicknameCache.put(key, nickname)
} else {
nicknameCache.put(key, NICKNAME_NULL)
}
return nickname
}
interface UserColorChangedListener {
fun onUserColorChanged(userKey: UserKey, color: Int)
}
interface UserNicknameChangedListener {
fun onUserNicknameChanged(userKey: UserKey, nick: String?)
}
private class OnColorPreferenceChangeListener internal constructor(private val mListener: UserColorChangedListener?) : OnSharedPreferenceChangeListener {
override fun onSharedPreferenceChanged(preferences: SharedPreferences, key: String) {
val userKey = UserKey.valueOf(key)
mListener?.onUserColorChanged(userKey, preferences.getInt(key, 0))
}
}
private class OnNickPreferenceChangeListener internal constructor(private val mListener: UserNicknameChangedListener?) : OnSharedPreferenceChangeListener {
override fun onSharedPreferenceChanged(preferences: SharedPreferences, key: String) {
val userKey = UserKey.valueOf(key)
mListener?.onUserNicknameChanged(userKey, preferences.getString(key, null))
}
}
companion object {
private val NICKNAME_NULL = ".#NULL#"
fun decideDisplayName(nickname: String?, name: String, screenName: String,
nameFirst: Boolean) = nickname ?: if (nameFirst) name else "@$screenName"
fun decideNickname(nick: String?, name: String) = nick ?: name
}
}