台达PLC程序解密

    科技2026-06-06  9

    台达PLC程序解密【专业】【信誉】【18230062509】说起 BaseActivity 和 BaseFragment,这里要写的东西一定要考虑好,因为这里的东西一定要是绝大多数类都能用到的方法,还有一些是要留给子类实现的。说到这里就需要想一下什么是绝大多数类都能用到的方法,看过项目介绍的应该知道项目实现了五种不同的状态:正常显示内容、加载中、没有网络、没有内容、加载错误,很显然,这些内容都应该写在 BaseActivity 和 BaseFragment 中,那么接下来就到了激动人心的码代码环节! 1、1 BaseActivity abstract class BaseActivity : AppCompatActivity(){

    /** * Activity中显示加载等待的控件。 */ private var loading: ProgressBar? = null /** * Activity中由于服务器异常导致加载失败显示的布局。 */ private var loadErrorView: View? = null /** * Activity中由于网络异常导致加载失败显示的布局。 */ private var badNetworkView: View? = null /** * Activity中当界面上没有任何内容时展示的布局。 */ private var noContentView: View? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setupViews() } protected open fun setupViews() { loading = findViewById(R.id.loading) noContentView = findViewById(R.id.noContentView) badNetworkView = findViewById(R.id.badNetworkView) loadErrorView = findViewById(R.id.loadErrorView) if (loading == null) { Log.e(TAG, "loading is null") } if (badNetworkView == null) { Log.e(TAG, "badNetworkView is null") } if (loadErrorView == null) { Log.e(TAG, "loadErrorView is null") } } companion object { private const val TAG = "BaseActivity" }

    }

    复制代码 好了,先放这么多,放太多会懵逼的。。。来看下代码吧:首先设置为抽象类是为啥就不说了,这个不知道的话该去学习 Java 基础了,然后把需要的 View 都找到,接下来就需要一个接口了,需要把在 Activity 或 Fragment 中进行数据请求所需要经历的生命周期函数抽出来,这样 BaseActivity 和 BaseFragment 就可以重复利用了,说干就干: interface RequestLifecycle {

    fun startLoading() fun loadFinished() fun loadFailed(msg: String?)

    } 复制代码 那么接下来接该改造下 BaseActivity 了: abstract class BaseActivity : AppCompatActivity(), RequestLifecycle {

    /** * 当Activity中的加载内容服务器返回失败,通过此方法显示提示界面给用户。 * * @param tip * 界面中的提示信息 */ protected fun showLoadErrorView(tip: String = "加载数据失败") { loadFinished() if (loadErrorView != null) { val loadErrorText = loadErrorView?.findViewById<TextView>(R.id.loadErrorText) loadErrorText?.text = tip loadErrorView?.visibility = View.VISIBLE return } } /** * 当Activity中的内容因为网络原因无法显示的时候,通过此方法显示提示界面给用户。 * * @param listener * 重新加载点击事件回调 */ protected fun showBadNetworkView(listener: View.OnClickListener) { loadFinished() if (badNetworkView != null) { badNetworkView?.visibility = View.VISIBLE badNetworkView?.setOnClickListener(listener) return } } /** * 当Activity中没有任何内容的时候,通过此方法显示提示界面给用户。 * @param tip * 界面中的提示信息 */ protected fun showNoContentView(tip: String) { loadFinished() val noContentText = noContentView?.findViewById<TextView>(R.id.noContentText) noContentText?.text = tip noContentView?.visibility = View.VISIBLE } /** * 将load error view进行隐藏。 */ private fun hideLoadErrorView() { loadErrorView?.visibility = View.GONE } /** * 将no content view进行隐藏。 */ private fun hideNoContentView() { noContentView?.visibility = View.GONE } /** * 将bad network view进行隐藏。 */ private fun hideBadNetworkView() { badNetworkView?.visibility = View.GONE } @CallSuper override fun startLoading() { hideBadNetworkView() hideNoContentView() hideLoadErrorView() loading?.visibility = View.VISIBLE } @CallSuper override fun loadFinished() { loading?.visibility = View.GONE hideBadNetworkView() hideNoContentView() hideLoadErrorView() } @CallSuper override fun loadFailed(msg: String?) { loading?.visibility = View.GONE hideBadNetworkView() hideNoContentView() hideLoadErrorView() }

    } 复制代码 写到这里已经有大概的样子了,这里解释下 @CallSuper 这个注解:表示任何重写方法都应该调用此方法。接下来该干什么呢?刚才说过,有些很多类能用到,并且可以父类实现的咱们已经实现了,还有一种就是需要子类来实现的,比如:加载布局、加载页面、加载具体数据等等,不管是 Activity 或者是 Fragment 都需要,但是都必须是子类来实现的,那么也可以写一个接口来抽出来: interface BaseInit {

    fun initData() fun initView() fun getLayoutId(): Int

    } 复制代码 很清晰吧,加载数据、加载View、获取布局,那就可以继续完善下 BaseActivity 了: abstract class BaseActivity : AppCompatActivity(), RequestLifecycle, BaseInit {

    override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) transparentStatusBar() setContentView(getLayoutId()) initView() initData() } override fun setContentView(layoutResID: Int) { super.setContentView(layoutResID) setupViews() } /** * 将状态栏设置成透明。只适配Android 5.0以上系统的手机。 */ private fun transparentStatusBar() { if (AndroidVersion.hasLollipop()) { val decorView = window.decorView decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE window.statusBarColor = Color.TRANSPARENT } }

    } 复制代码 这块来干了两件事:1、实现了初始化的接口并调用;2、将状态栏设置为透明,因为目前所有应用都实现了沉浸式。 不知道大家注意到没有,在父类中直接能实现的接口都实现了,但是需要在子类中实现的接口都没有实现,这就相当于在父类中直接写抽象方法,为了能和 BaseFragment 复用,所以提取成了接口,但并不在父类中进行实现从而交给了子类来实现。 最后再给 BaseActivity 加一个功能就差不多了:Activity 控制器,有很多情况下我们想把之前打开的 Activity 给一次性关闭,但是很麻烦,所以要实现一个 Activity 的控制器,每次 Activity 在执行 onCreate 方法的时候加入到控制器中,onDestroy 方法的时候从控制器中移除掉,来吧,写一个吧: object ActivityCollector {

    private const val TAG = "ActivityCollector" private val activityList = ArrayList<WeakReference<Activity>?>() fun size(): Int { return activityList.size } fun add(weakRefActivity: WeakReference<Activity>?) { activityList.add(weakRefActivity) } fun remove(weakRefActivity: WeakReference<Activity>?) { val result = activityList.remove(weakRefActivity) Log.d(TAG, "remove activity reference $result") } fun finishAll() { if (activityList.isNotEmpty()) { for (activityWeakReference in activityList) { val activity = activityWeakReference?.get() if (activity != null && !activity.isFinishing) { activity.finish() } } activityList.clear() } }

    } 复制代码 上面这个类很简单,只是一个 ArrayList ,进行添加和移除操作,这里需要注意的是为了防止内存泄露使用到了弱引用。 接下来就该把这个控制器添加到 BaseActivity 中了: private var weakRefActivity: WeakReference? = null

    override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ActivityCollector.add(WeakReference(this)) weakRefActivity = WeakReference(this) } override fun onDestroy() { super.onDestroy() ActivityCollector.remove(weakRefActivity) }

    复制代码 好了,BaseActivity 到这里就差不多了,放一个完整版的吧: abstract class BaseActivity : AppCompatActivity(), RequestLifecycle, BaseInit {

    /** * Activity中显示加载等待的控件。 */ private var loading: ProgressBar? = null /** * Activity中由于服务器异常导致加载失败显示的布局。 */ private var loadErrorView: View? = null /** * Activity中由于网络异常导致加载失败显示的布局。 */ private var badNetworkView: View? = null /** * Activity中当界面上没有任何内容时展示的布局。 */ private var noContentView: View? = null private var weakRefActivity: WeakReference<Activity>? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) transparentStatusBar() setContentView(getLayoutId()) ActivityCollector.add(WeakReference(this)) weakRefActivity = WeakReference(this) initView() initData() } override fun onDestroy() { super.onDestroy() ActivityCollector.remove(weakRefActivity) } override fun setContentView(layoutResID: Int) { super.setContentView(layoutResID) setupViews() } protected open fun setupViews() { loading = findViewById(R.id.loading) noContentView = findViewById(R.id.noContentView) badNetworkView = findViewById(R.id.badNetworkView) loadErrorView = findViewById(R.id.loadErrorView) if (loading == null) { Log.e(TAG, "loading is null") } if (badNetworkView == null) { Log.e(TAG, "badNetworkView is null") } if (loadErrorView == null) { Log.e(TAG, "loadErrorView is null") } } /** * 将状态栏设置成透明。只适配Android 5.0以上系统的手机。 */ private fun transparentStatusBar() { if (AndroidVersion.hasLollipop()) { val decorView = window.decorView decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE window.statusBarColor = Color.TRANSPARENT } } /** * 当Activity中的加载内容服务器返回失败,通过此方法显示提示界面给用户。 * * @param tip * 界面中的提示信息 */ protected fun showLoadErrorView(tip: String = "加载数据失败") { loadFinished() if (loadErrorView != null) { val loadErrorText = loadErrorView?.findViewById<TextView>(R.id.loadErrorText) loadErrorText?.text = tip loadErrorView?.visibility = View.VISIBLE return } } /** * 当Activity中的内容因为网络原因无法显示的时候,通过此方法显示提示界面给用户。 * * @param listener * 重新加载点击事件回调 */ protected fun showBadNetworkView(listener: View.OnClickListener) { loadFinished() if (badNetworkView != null) { badNetworkView?.visibility = View.VISIBLE badNetworkView?.setOnClickListener(listener) return } } /** * 当Activity中没有任何内容的时候,通过此方法显示提示界面给用户。 * @param tip * 界面中的提示信息 */ protected fun showNoContentView(tip: String) { loadFinished() val noContentText = noContentView?.findViewById<TextView>(R.id.noContentText) noContentText?.text = tip noContentView?.visibility = View.VISIBLE } /** * 将load error view进行隐藏。 */ private fun hideLoadErrorView() { loadErrorView?.visibility = View.GONE } /** * 将no content view进行隐藏。 */ private fun hideNoContentView() { noContentView?.visibility = View.GONE } /** * 将bad network view进行隐藏。 */ private fun hideBadNetworkView() { badNetworkView?.visibility = View.GONE } @CallSuper override fun startLoading() { hideBadNetworkView() hideNoContentView() hideLoadErrorView() loading?.visibility = View.VISIBLE } @CallSuper override fun loadFinished() { loading?.visibility = View.GONE hideBadNetworkView() hideNoContentView() hideLoadErrorView() } @CallSuper override fun loadFailed(msg: String?) { loading?.visibility = View.GONE hideBadNetworkView() hideNoContentView() hideLoadErrorView() } companion object { private const val TAG = "BaseActivity" }

    } 复制代码 BaseFragment 其实 BaseFragment 和 BaseActivity 基本一样,只是加载布局的地方有所不同,大家都是老司机,应该都懂: /** * Fragment中inflate出来的布局。 */ private var rootView: View? = null

    override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(getLayoutId(), container, false) onCreateView(view) return view } /** * 在Fragment基类中获取通用的控件,会将传入的View实例原封不动返回。 * @param view * Fragment中inflate出来的View实例。 * @return Fragment中inflate出来的View实例原封不动返回。 */ private fun onCreateView(view: View): View { rootView = view loading = view.findViewById(R.id.loading) noContentView = view.findViewById(R.id.noContentView) badNetworkView = view.findViewById(R.id.badNetworkView) loadErrorView = view.findViewById(R.id.loadErrorView) if (loading == null) { throw NullPointerException("loading is null") } if (badNetworkView == null) { throw NullPointerException("badNetworkView is null") } if (loadErrorView == null) { throw NullPointerException("loadErrorView is null") } return view }

    复制代码 细心的大家应该都看出来了,在 BaseActivity 中如果 View 为空我只打印了 log 值,但在 BaseFragment 中却抛了异常!这里其实看需求来写,如果你认为你的实现都必须要实现 LCE ,那么就直接抛出,这样运行的时候就可以直接看出问题了,如果没必要的话打印个 log 值知道就可以了,没什么特别的深意。 LCE 布局 上面 BaseActivity 和 BaseFragment 中都提到的布局还没写呢!接下来写下布局吧: 一个一个来吧,先来没有内容的布局吧!

    <?xml version="1.0" encoding="utf-8"?>

    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:orientation="vertical"> <ImageView android:layout_width="@dimen/dp_80" android:layout_height="@dimen/dp_80" android:layout_gravity="center_horizontal" android:src="@drawable/no_content_image" /> <TextView android:id="@+id/noContentText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="@dimen/dp_20" android:layout_marginBottom="@dimen/dp_20" android:textSize="@dimen/sp_13" android:textColor="@color/secondary_text" tools:text="没有更多内容了"/> </LinearLayout>
    Processed: 0.011, SQL: 9