kotlin 编写一个简单的天气预报app(二)

增加界面显示openweathermap返回的信息。

在activity_main.xml里增加输入框来输入城市,在输入款旁边增加搜索按钮来进行查询。

然后原来显示helloworld的TextView用来显示结果。

1. 增加输入城市名字的EditText

xml 复制代码
    <EditText
        android:id="@+id/editTextCity"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="@string/editTextCityHint"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/buttonSearch"/>
  1. 增加搜索按钮
xml 复制代码
    <Button
        android:id="@+id/buttonSearch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="@+id/editTextCity"
        app:layout_constraintBottom_toBottomOf="@+id/editTextCity"
        app:layout_constraintStart_toEndOf="@+id/editTextCity"
        app:layout_constraintEnd_toEndOf="parent"
        android:text="@string/buttonSearchText" />

3. 增加显示的TextView

xml 复制代码
    <TextView
        android:id="@+id/weatherResult"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

使用broadcast的方式把收到的天气信息发送到界面显示。

Android的广播机制是一种用于在应用程序内和应用程序之间传递消息和事件的方式。通过广播,一个应用程序可以发送消息(被称为广播),而其他应用程序可以接收并处理这些广播。

  • 广播发送者(Broadcast Sender):应用程序或者系统组件(如系统服务)可以通过发送广播来通知其他应用程序或组件事件的发生。广播发送者并不需要知道接收者是谁,只需要发送广播即可。
  • 广播接收者(Broadcast Receiver):应用程序或者组件可以通过注册广播接收器来接收特定类型的广播。广播接收者可以在AndroidManifest.xml文件中声明静态接收器,也可以在代码中动态注册接收器。
  • 广播的类型:Android广播可以分为普通广播和有序广播两种类型。
  • 普通广播(Normal Broadcast):普通广播是一种异步的广播发送方式,广播发送者不需要等待接收者处理广播。这使得广播发送者能够快速地发送广播,而不会受到接收者处理时间的影响。
  • 有序广播(Ordered Broadcast):有序广播是一种同步的广播发送方式,广播发送者会按照优先级的顺序发送广播,接收者依次处理广播。每个接收者处理完广播后可以选择终止广播或者将广播传递给下一个接收者。
  • 广播过滤器(Broadcast Filter):广播过滤器允许应用程序指定它们所感兴趣的广播类型。广播接收者可以根据广播过滤器过滤来自特定来源或具有特定操作的广播。这样可以减少不必要的广播传递,提高性能。
  • 系统广播(System Broadcast):Android系统内置了一些广播用于通知应用程序和组件系统事件的发生,例如设备启动、网络连接状态变化、电池低电量等。应用程序可以注册对这些系统广播感兴趣的接收者,以执行相应的操作。
    通过广播机制,应用程序可以实现一种松耦合的通信方式,让不同的组件之间进行信息传递和事件触发。这种机制使得应用程序能够更好地响应系统事件、应用程序状态的变化,并且可以与其他应用程序之间进行交互。

4.注册一个自定义的广播:

将广播接收器的类名替换为您自己的接收器类名,并使用 intent-filter 添加您自定义的广播 action。

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.INTERNET" />
    <application
<!--   			... -->
        <activity
<!--   			... -->
        </activity>
        <receiver
            android:name=".WeatherResponseReceiver"
            android:exported="false">
            <intent-filter>
                <action android:name="com.example.MyWeather.ACTION_WEATHER_DATA"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>

5.在RetrofitClient类中发送广播

在发送自定义广播时,您需要使用 sendBroadcast() 方法,并指定广播的 action。

kotlin 复制代码
    private fun handleWeatherData(context: Context, weatherData: WeatherResponse?) {
        if (weatherData != null) {
            val intent = Intent("com.example.MyWeather.ACTION_WEATHER_DATA")
            intent.putExtra("cityName", weatherData.name)
            intent.putExtra("temperature", weatherData.main?.temp)
            intent.putExtra("maxTemperature", weatherData.main?.temp_max)
            intent.putExtra("minTemperature", weatherData.main?.temp_min)
            val weatherStringArray = arrayListOf<String>()
            for(weather in weatherData.weather) {
                weatherStringArray += "main:${weather.main},description:${weather.description}"
            }
            intent.putStringArrayListExtra("weather", weatherStringArray)
            context.sendBroadcast(intent)

            printWeatherData(weatherData)
        }
    }

6.创建一个用来接受广播的类,并重写onReceive函数。

kotlin 复制代码
class WeatherResponseReceiver : BroadcastReceiver() {
    private var textView: TextView? = null

    fun setTextView(textView: TextView) {
        this.textView = textView
    }


    override fun onReceive(context: Context?, intent: Intent?) {
        if(intent?.action == "com.example.MyWeather.ACTION_WEATHER_DATA") {
            val kelvins = 273.15
            val cityName = intent.getStringExtra("cityName")
            val temperature = intent.getFloatExtra("temperature", 0.0F) - kelvins
            val maxTemperature = intent.getFloatExtra("maxTemperature", 0.0F) - kelvins
            val minTemperature = intent.getFloatExtra("minTemperature", 0.0F) - kelvins
            val weather = intent.getStringArrayListExtra("weather")
            val decimalFormat = DecimalFormat("#.#")

            @SuppressLint("SetTextI18n")
            textView?.text = "$cityName\n${decimalFormat.format(temperature)}\n${decimalFormat.format(maxTemperature)}\n${decimalFormat.format(minTemperature)}\n$weather"
        }
    }
}

为了能让收到的广播消息能够显示在TextView中,我把TextView的指针传递给了接收广播的类。

kotlin 复制代码
class MainActivity : AppCompatActivity() {
    private lateinit var weatherResponseReceiver: WeatherResponseReceiver

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        weatherResponseReceiver = WeatherResponseReceiver()
        weatherResponseReceiver.setTextView(findViewById<TextView>(R.id.weatherResult))
        val intentFilter = IntentFilter("com.example.MyWeather.ACTION_WEATHER_DATA")
        registerReceiver(weatherResponseReceiver, intentFilter)

        findViewById<Button>(R.id.buttonSearch).setOnClickListener { searchCityNameWeather(it) }
    }

    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(weatherResponseReceiver)
    }

    private fun searchCityNameWeather(view: View) {
        val cityName = findViewById<EditText>(R.id.editTextCity).text.toString().trim()
        RetrofitClient.getWeatherByCityName(view.context, cityName)
    }
}

7.最后的测试结果:

相关推荐
Indoraptor1 小时前
Android Fence 同步框架
android
峥嵘life1 小时前
DeepSeek本地搭建 和 Android
android
叶羽西1 小时前
Android14 Camera框架中Jpeg流buffer大小的计算
android·安卓
jiasting1 小时前
Android 中 如何监控 某个磁盘有哪些进程或线程在持续的读写
android
AnalogElectronic4 小时前
问题记录,在使用android studio 构建项目时遇到的问题
android·ide·android studio
我爱松子鱼5 小时前
mysql之InnoDB Buffer Pool 深度解析与性能优化
android·mysql·性能优化
江上清风山间明月8 小时前
Flutter开发的应用页面非常多时如何高效管理路由
android·flutter·路由·页面管理·routes·ongenerateroute
子非衣11 小时前
MySQL修改JSON格式数据示例
android·mysql·json
有点感觉13 小时前
Android级联选择器,下拉菜单
kotlin
openinstall全渠道统计14 小时前
免填邀请码工具:赋能六大核心场景,重构App增长新模型
android·ios·harmonyos