Skip to content

Commit

Permalink
Migrate to View Binding
Browse files Browse the repository at this point in the history
Use view binding to simplify some code
  • Loading branch information
yuhan6665 committed Jul 23, 2021
1 parent 54a191d commit ecb1d58
Show file tree
Hide file tree
Showing 12 changed files with 175 additions and 184 deletions.
4 changes: 4 additions & 0 deletions V2rayNG/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ android {
1000000 + android.defaultConfig.versionCode
}
}

buildFeatures {
viewBinding true
}
}

dependencies {
Expand Down
19 changes: 11 additions & 8 deletions V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/LogcatActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@ import android.view.MenuItem
import android.view.View
import com.v2ray.ang.AppConfig.ANG_PACKAGE
import com.v2ray.ang.R
import com.v2ray.ang.databinding.ActivityLogcatBinding
import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.Utils
import kotlinx.android.synthetic.main.activity_logcat.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.IOException
import java.util.LinkedHashSet

class LogcatActivity : BaseActivity() {
private lateinit var binding: ActivityLogcatBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_logcat)
binding = ActivityLogcatBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)

title = getString(R.string.title_logcat)

Expand All @@ -33,7 +36,7 @@ class LogcatActivity : BaseActivity() {
private fun logcat(shouldFlushLog: Boolean) {

try {
pb_waiting.visibility = View.VISIBLE
binding.pbWaiting.visibility = View.VISIBLE

GlobalScope.launch(Dispatchers.Default) {
if (shouldFlushLog) {
Expand All @@ -56,10 +59,10 @@ class LogcatActivity : BaseActivity() {
// val allText = bufferedReader.use(BufferedReader::readText)
val allText = process.inputStream.bufferedReader().use { it.readText() }
launch(Dispatchers.Main) {
tv_logcat.text = allText
tv_logcat.movementMethod = ScrollingMovementMethod()
pb_waiting.visibility = View.GONE
Handler(Looper.getMainLooper()).post { sv_logcat.fullScroll(View.FOCUS_DOWN) }
binding.tvLogcat.text = allText
binding.tvLogcat.movementMethod = ScrollingMovementMethod()
binding.pbWaiting.visibility = View.GONE
Handler(Looper.getMainLooper()).post { binding.svLogcat.fullScroll(View.FOCUS_DOWN) }
}
}
} catch (e: IOException) {
Expand All @@ -74,7 +77,7 @@ class LogcatActivity : BaseActivity() {

override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.copy_all -> {
Utils.setClipboard(this, tv_logcat.text.toString())
Utils.setClipboard(this, binding.tvLogcat.text.toString())
toast(R.string.toast_success)
true
}
Expand Down
57 changes: 30 additions & 27 deletions V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.v2ray.ang.AppConfig
import com.v2ray.ang.AppConfig.ANG_PACKAGE
import com.v2ray.ang.BuildConfig
import com.v2ray.ang.R
import com.v2ray.ang.databinding.ActivityMainBinding
import com.v2ray.ang.dto.EConfigType
import com.v2ray.ang.extension.toast
import com.v2ray.ang.helper.SimpleItemTouchHelperCallback
Expand All @@ -31,7 +32,6 @@ import com.v2ray.ang.util.AngConfigManager
import com.v2ray.ang.util.MmkvManager
import com.v2ray.ang.util.Utils
import com.v2ray.ang.viewmodel.MainViewModel
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
Expand All @@ -49,6 +49,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
private const val REQUEST_FILE_CHOOSER = 2
private const val REQUEST_SCAN_URL = 3
}
private lateinit var binding: ActivityMainBinding

private val adapter by lazy { MainRecyclerAdapter(this) }
private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) }
Expand All @@ -58,11 +59,13 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
title = getString(R.string.title_server)
setSupportActionBar(toolbar)
setSupportActionBar(binding.toolbar)

fab.setOnClickListener {
binding.fab.setOnClickListener {
if (mainViewModel.isRunning.value == true) {
Utils.stopVService(this)
} else if (settingsStorage?.decodeString(AppConfig.PREF_MODE) ?: "VPN" == "VPN") {
Expand All @@ -76,30 +79,30 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
startV2Ray()
}
}
layout_test.setOnClickListener {
binding.layoutTest.setOnClickListener {
if (mainViewModel.isRunning.value == true) {
tv_test_state.text = getString(R.string.connection_test_testing)
binding.tvTestState.text = getString(R.string.connection_test_testing)
mainViewModel.testCurrentServerRealPing()
} else {
// tv_test_state.text = getString(R.string.connection_test_fail)
}
}

recycler_view.setHasFixedSize(true)
recycler_view.layoutManager = LinearLayoutManager(this)
recycler_view.adapter = adapter
binding.recyclerView.setHasFixedSize(true)
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = adapter

val callback = SimpleItemTouchHelperCallback(adapter)
mItemTouchHelper = ItemTouchHelper(callback)
mItemTouchHelper?.attachToRecyclerView(recycler_view)
mItemTouchHelper?.attachToRecyclerView(binding.recyclerView)


val toggle = ActionBarDrawerToggle(
this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
drawer_layout.addDrawerListener(toggle)
this, binding.drawerLayout, binding.toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
binding.drawerLayout.addDrawerListener(toggle)
toggle.syncState()
nav_view.setNavigationItemSelectedListener(this)
version.text = "v${BuildConfig.VERSION_NAME} (${Libv2ray.checkVersionX()})"
binding.navView.setNavigationItemSelectedListener(this)
binding.version.text = "v${BuildConfig.VERSION_NAME} (${Libv2ray.checkVersionX()})"

setupViewModelObserver()
migrateLegacy()
Expand All @@ -114,18 +117,18 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
adapter.notifyDataSetChanged()
}
})
mainViewModel.updateTestResultAction.observe(this, { tv_test_state.text = it })
mainViewModel.updateTestResultAction.observe(this, { binding.tvTestState.text = it })
mainViewModel.isRunning.observe(this, {
val isRunning = it ?: return@observe
adapter.isRunning = isRunning
if (isRunning) {
fab.setImageResource(R.drawable.ic_v)
tv_test_state.text = getString(R.string.connection_connected)
layout_test.isFocusable = true
binding.fab.setImageResource(R.drawable.ic_v)
binding.tvTestState.text = getString(R.string.connection_connected)
binding.layoutTest.isFocusable = true
} else {
fab.setImageResource(R.drawable.ic_v_idle)
tv_test_state.text = getString(R.string.connection_not_connected)
layout_test.isFocusable = false
binding.fab.setImageResource(R.drawable.ic_v_idle)
binding.tvTestState.text = getString(R.string.connection_not_connected)
binding.layoutTest.isFocusable = false
}
hideCircle()
})
Expand Down Expand Up @@ -505,25 +508,25 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
}

fun showCircle() {
fabProgressCircle?.show()
binding.fabProgressCircle?.show()
}

fun hideCircle() {
try {
Observable.timer(300, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
if (fabProgressCircle.isShown) {
fabProgressCircle.hide()
if (binding.fabProgressCircle.isShown) {
binding.fabProgressCircle.hide()
}
}
} catch (e: Exception) {
}
}

override fun onBackPressed() {
if (drawer_layout.isDrawerOpen(GravityCompat.START)) {
drawer_layout.closeDrawer(GravityCompat.START)
if (binding.drawerLayout.isDrawerOpen(GravityCompat.START)) {
binding.drawerLayout.closeDrawer(GravityCompat.START)
} else {
super.onBackPressed()
}
Expand Down Expand Up @@ -553,7 +556,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
startActivity(Intent(this, LogcatActivity::class.java))
}
}
drawer_layout.closeDrawer(GravityCompat.START)
binding.drawerLayout.closeDrawer(GravityCompat.START)
return true
}
}
84 changes: 32 additions & 52 deletions V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import com.google.gson.Gson
import com.tencent.mmkv.MMKV
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.databinding.ItemQrcodeBinding
import com.v2ray.ang.databinding.ItemRecyclerFooterBinding
import com.v2ray.ang.databinding.ItemRecyclerMainBinding
import com.v2ray.ang.dto.EConfigType
import com.v2ray.ang.dto.SubscriptionItem
import com.v2ray.ang.extension.toast
Expand All @@ -21,8 +24,6 @@ import com.v2ray.ang.service.V2RayServiceManager
import com.v2ray.ang.util.AngConfigManager
import com.v2ray.ang.util.MmkvManager
import com.v2ray.ang.util.Utils
import kotlinx.android.synthetic.main.item_qrcode.view.*
import kotlinx.android.synthetic.main.item_recycler_main.view.*
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import java.util.concurrent.TimeUnit
Expand Down Expand Up @@ -51,44 +52,44 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
val outbound = config.getProxyOutbound()
val aff = MmkvManager.decodeServerAffiliationInfo(guid)

holder.name.text = config.remarks
holder.radio.isChecked = guid == mainStorage?.decodeString(MmkvManager.KEY_SELECTED_SERVER)
holder.itemMainBinding.tvName.text = config.remarks
holder.itemMainBinding.btnRadio.isChecked = guid == mainStorage?.decodeString(MmkvManager.KEY_SELECTED_SERVER)
holder.itemView.setBackgroundColor(Color.TRANSPARENT)
holder.test_result.text = aff?.getTestDelayString() ?: ""
holder.itemMainBinding.tvTestResult.text = aff?.getTestDelayString() ?: ""
if (aff?.testDelayMillis?:0L < 0L) {
holder.test_result.setTextColor(ContextCompat.getColor(mActivity, android.R.color.holo_red_dark))
holder.itemMainBinding.tvTestResult.setTextColor(ContextCompat.getColor(mActivity, android.R.color.holo_red_dark))
} else {
holder.test_result.setTextColor(ContextCompat.getColor(mActivity, R.color.colorPing))
holder.itemMainBinding.tvTestResult.setTextColor(ContextCompat.getColor(mActivity, R.color.colorPing))
}
holder.subscription.text = ""
holder.itemMainBinding.tvSubscription.text = ""
val json = subStorage?.decodeString(config.subscriptionId)
if (!json.isNullOrBlank()) {
val sub = Gson().fromJson(json, SubscriptionItem::class.java)
holder.subscription.text = sub.remarks
holder.itemMainBinding.tvSubscription.text = sub.remarks
}

var shareOptions = share_method.asList()
if (config.configType == EConfigType.CUSTOM) {
holder.type.text = mActivity.getString(R.string.server_customize_config)
holder.itemMainBinding.tvType.text = mActivity.getString(R.string.server_customize_config)
shareOptions = shareOptions.takeLast(1)
} else if (config.configType == EConfigType.VLESS) {
holder.type.text = config.configType.name
holder.itemMainBinding.tvType.text = config.configType.name
} else {
holder.type.text = config.configType.name.toLowerCase()
holder.itemMainBinding.tvType.text = config.configType.name.toLowerCase()
}
holder.statistics.text = "${outbound?.getServerAddress()} : ${outbound?.getServerPort()}"
holder.itemMainBinding.tvStatistics.text = "${outbound?.getServerAddress()} : ${outbound?.getServerPort()}"

holder.layout_share.setOnClickListener {
holder.itemMainBinding.layoutShare.setOnClickListener {
AlertDialog.Builder(mActivity).setItems(shareOptions.toTypedArray()) { _, i ->
try {
when (i) {
0 -> {
if (config.configType == EConfigType.CUSTOM) {
shareFullContent(guid)
} else {
val iv = LayoutInflater.from(mActivity).inflate(R.layout.item_qrcode, null)
iv.iv_qcode.setImageBitmap(AngConfigManager.share2QRCode(guid))
AlertDialog.Builder(mActivity).setView(iv).show()
val ivBinding = ItemQrcodeBinding.inflate(LayoutInflater.from(mActivity))
ivBinding.ivQcode.setImageBitmap(AngConfigManager.share2QRCode(guid))
AlertDialog.Builder(mActivity).setView(ivBinding.root).show()
}
}
1 -> {
Expand All @@ -107,7 +108,7 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
}.show()
}

holder.layout_edit.setOnClickListener {
holder.itemMainBinding.layoutEdit.setOnClickListener {
val intent = Intent().putExtra("guid", guid)
.putExtra("isRunning", isRunning)
if (config.configType == EConfigType.CUSTOM) {
Expand All @@ -116,15 +117,15 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
mActivity.startActivity(intent.setClass(mActivity, ServerActivity::class.java))
}
}
holder.layout_remove.setOnClickListener {
holder.itemMainBinding.layoutRemove.setOnClickListener {
if (guid != mainStorage?.decodeString(MmkvManager.KEY_SELECTED_SERVER)) {
mActivity.mainViewModel.removeServer(guid)
notifyItemRemoved(position)
notifyItemRangeChanged(position, mActivity.mainViewModel.serverList.size)
}
}

holder.infoContainer.setOnClickListener {
holder.itemMainBinding.infoContainer.setOnClickListener {
val selected = mainStorage?.decodeString(MmkvManager.KEY_SELECTED_SERVER)
if (guid != selected) {
mainStorage?.encode(MmkvManager.KEY_SELECTED_SERVER, guid)
Expand All @@ -146,9 +147,9 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
if (holder is FooterViewHolder) {
//if (activity?.defaultDPreference?.getPrefBoolean(AppConfig.PREF_INAPP_BUY_IS_PREMIUM, false)) {
if (true) {
holder.layout_edit.visibility = View.INVISIBLE
holder.itemFooterBinding.layoutEdit.visibility = View.INVISIBLE
} else {
holder.layout_edit.setOnClickListener {
holder.itemFooterBinding.layoutEdit.setOnClickListener {
Utils.openUri(mActivity, "${Utils.decode(AppConfig.promotionUrl)}?t=${System.currentTimeMillis()}")
}
}
Expand All @@ -166,11 +167,9 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
return when (viewType) {
VIEW_TYPE_ITEM ->
MainViewHolder(LayoutInflater.from(parent.context)
.inflate(R.layout.item_recycler_main, parent, false))
MainViewHolder(ItemRecyclerMainBinding.inflate(LayoutInflater.from(parent.context), parent, false))
else ->
FooterViewHolder(LayoutInflater.from(parent.context)
.inflate(R.layout.item_recycler_footer, parent, false))
FooterViewHolder(ItemRecyclerFooterBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
}

Expand All @@ -182,40 +181,21 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter<Mai
}
}

open class BaseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

class MainViewHolder(itemView: View) : BaseViewHolder(itemView), ItemTouchHelperViewHolder {
val subscription = itemView.tv_subscription!!
val radio = itemView.btn_radio!!
val name = itemView.tv_name!!
val test_result = itemView.tv_test_result!!
val type = itemView.tv_type!!
val statistics = itemView.tv_statistics!!
val infoContainer = itemView.info_container!!
val layout_edit = itemView.layout_edit!!
val layout_share = itemView.layout_share
val layout_remove = itemView.layout_remove!!

override fun onItemSelected() {
open class BaseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun onItemSelected() {
itemView.setBackgroundColor(Color.LTGRAY)
}

override fun onItemClear() {
fun onItemClear() {
itemView.setBackgroundColor(0)
}
}

class FooterViewHolder(itemView: View) : BaseViewHolder(itemView), ItemTouchHelperViewHolder {
val layout_edit = itemView.layout_edit!!
class MainViewHolder(val itemMainBinding: ItemRecyclerMainBinding) :
BaseViewHolder(itemMainBinding.root), ItemTouchHelperViewHolder

override fun onItemSelected() {
itemView.setBackgroundColor(Color.LTGRAY)
}

override fun onItemClear() {
itemView.setBackgroundColor(0)
}
}
class FooterViewHolder(val itemFooterBinding: ItemRecyclerFooterBinding) :
BaseViewHolder(itemFooterBinding.root), ItemTouchHelperViewHolder

override fun onItemDismiss(position: Int) {
val guid = mActivity.mainViewModel.serverList.getOrNull(position) ?: return
Expand Down
Loading

0 comments on commit ecb1d58

Please sign in to comment.