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.最后的测试结果:

相关推荐
市场部需要一个软件开发岗位22 分钟前
JAVA开发常见安全问题:Cookie 中明文存储用户名、密码
android·java·安全
JMchen1232 小时前
Android后台服务与网络保活:WorkManager的实战应用
android·java·网络·kotlin·php·android-studio
crmscs3 小时前
剪映永久解锁版/电脑版永久会员VIP/安卓SVIP手机永久版下载
android·智能手机·电脑
localbob3 小时前
杀戮尖塔 v6 MOD整合版(Slay the Spire)安卓+PC端免安装中文版分享 卡牌肉鸽神作!杀戮尖塔中文版,电脑和手机都能玩!杀戮尖塔.exe 杀戮尖塔.apk
android·杀戮尖塔apk·杀戮尖塔exe·游戏分享
机建狂魔3 小时前
手机秒变电影机:Blackmagic Camera + LUT滤镜包的专业级视频解决方案
android·拍照·摄影·lut滤镜·拍摄·摄像·录像
hudawei9963 小时前
flutter和Android动画的对比
android·flutter·动画
lxysbly5 小时前
md模拟器安卓版带金手指2026
android
儿歌八万首6 小时前
硬核春节:用 Compose 打造“赛博鞭炮”
android·kotlin·compose·春节
消失的旧时光-19438 小时前
从 Kotlin 到 Dart:为什么 sealed 是处理「多种返回结果」的最佳方式?
android·开发语言·flutter·架构·kotlin·sealed
有位神秘人8 小时前
kotlin与Java中的单例模式总结
java·单例模式·kotlin