[Android]常见的数据传递方式

Demo:https://github.com/Gamin-fzym/DataTransferDemo

1.Intent

发送页面 A 到页面 B 的 Intent 时,可以通过 Intent 的 putExtra() 方法将数据附加到 Intent 上。

在页面 B 中,通过 Intent 的 getXXXExtra() 方法获取传递的数据。

1).在A页面发送 Intent

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import com.example.datatransferdemo.databinding.ActivityMainBinding
import com.example.datatransferdemo.pageb.PageB1


class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    // 获取返回结果,在Activity或Fragment中定义
    private val someActivityResultLauncher = registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            // 执行成功后的操作
            val intent: Intent? = result.data
            when (intent?.tag) {
                "PageB1" -> {
                    var resultValue = intent?.getStringExtra("result_key")
                }
                "PageB2" -> {
                    val bundle = intent?.extras
                }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 1.Intent
        binding.button1.setOnClickListener {
            val intent = Intent(this, PageB1::class.java)
            intent.putExtra("key", "传递字符串") // 可选:添加要传递的数据
            // 启动目标 Activity
            //startActivity(intent)
            // 如果希望在目标 Activity 中获取返回结果,使用ActivityResultLauncher来启动
            someActivityResultLauncher.launch(intent);
        }
    }

}

2).在B页面接收数据

import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.example.datatransferdemo.R

class PageB1 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_page_b1)

        // 获取传递过来的值
        val value = intent.getStringExtra("key")

        // 离开回传数据
        val but = findViewById<Button>(R.id.button)
        but.setOnClickListener {
            val returnIntent = Intent()
            returnIntent.tag = "PageB1"
            returnIntent.putExtra("result_key", "返回字符串")
            setResult(RESULT_OK, returnIntent)

            finish() // 结束当前Activity, 不一定要立即结束。
        }
    }
}

3).拓展Intent用来区分回传数据

使用扩展函数为 Intent 添加一个自定义的 tag属性

import android.content.Intent

var Intent.tag: String?
    get() = getStringExtra("tag")
    set(value) {
        putExtra("tag", value)
    }

2.Bundle

类似于 Intent,可以使用 Bundle 在页面间传递数据。

在发送页面 A 到页面 B 的过程中,将数据放入 Bundle 对象中。

在接收页面 B 中,从 Intent 中获取 Bundle 对象,并从 Bundle 中提取数据。

1).在A页面发送 Bundle

val bundle = Bundle()
bundle.putInt("id",123)
bundle.putBoolean("status",true)
bundle.putString("content", "传递字符串")
val intent = Intent(this, PageB2::class.java)
intent.putExtras(bundle)
// 启动目标 Activity
//startActivity(intent)
// 获取返回结果启动
someActivityResultLauncher.launch(intent);

2).在B页面接收数据

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.example.datatransferdemo.R
import com.example.datatransferdemo.tag

class PageB2 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_page_b2)

        // 获取传递过来的值
        val bundle = intent.extras
        val receivedID = bundle?.getInt("id") // 根据传递的数据类型使用对应的 getXXX() 方法
        val receivedStatus = bundle?.getBoolean("status")
        val receivedContent = bundle?.getString("content")

        // 离开回传数据
        val returnBundle = Bundle()
        returnBundle.putInt("id",123)
        returnBundle.putBoolean("status",true)
        returnBundle.putString("content", "传递字符串")
        val returnIntent = Intent()
        returnIntent.tag = "PageB2"
        returnIntent.putExtras(returnBundle)
        setResult(RESULT_OK, returnIntent)
    }
}

3.静态变量

在一个类中定义一个静态变量,其他页面可以直接访问该静态变量来传递数据。

适用于全局范围内需要传递数据的情况,但不适用于临时或有生命周期的数据传递。

1).定义静态变量

object StaticDataHolder {
    var sharedData = mapOf<String,String>()
}

2).在A页面设置数据

 StaticDataHolder.sharedData = mapOf<String,String>("id" to "1234", "status" to "1", "content" to "传递字符串")

3).在B页面获取数据

val receivedData = StaticDataHolder.sharedData

4.SharedPreferences

使用 SharedPreferences 可以存储和读取键值对数据,并在不同页面间共享数据。

适用于需要长期存储和共享数据的情况。

1).在A页面设置数据

val sharedPref = getSharedPreferences("my_prefs", Context.MODE_PRIVATE)
val editor = sharedPref.edit()
editor.putString("key", data) // data 是要传递的数据
editor.apply()

2).在B页面获取数据

val sharedPref = getSharedPreferences("my_prefs", Context.MODE_PRIVATE)
val receivedData = sharedPref.getString("key", "") // 根据传递的数据类型使用对应的 getXXX() 方法

5.接口回调(Interface Callback)

定义一个接口,在页面 A 中实现该接口,并将实现类的实例传递给页面 B。

页面 B 可以调用接口的方法来传递数据给页面 A。

适用于页面间有交互和回调需求的情况。

1).定义接口

interface DataCallback {
    fun onDataReceived(data: String)
}

2).在页面 A 中实现接口

class PageA : AppCompatActivity(), DataCallback {
  
    // 静态的DataCallback实例
    companion object {
        var callbackInstance: DataCallback? = null
    }
        
    override fun onDestroy() {
        super.onDestroy()
        callbackInstance = null // 防止内存泄漏
    }        
        
    override fun onDataReceived(data: String) {
        // 处理接收到的数据
    }

    // 在需要传递数据的地方将实现类的实例传递给页面 B
    callbackInstance = this;
    val intent = Intent(this, PageB5::class.java)
    startActivity(intent)
}

3).在页面 B 中使用接口传递数据

  // 调用DataCallback的方法
  if (MainActivity.callbackInstance != null) {
      MainActivity.callbackInstance?.onDataReceived("传递的数据")
  }

6.EventBus

使用 EventBus 库来进行页面间的事件传递和数据通信。

页面 A 发布一个事件,页面 B 订阅该事件并接收数据。

适用于解耦和简化页面间通信的情况。

1).添加 EventBus 到你的项目依赖中

dependencies {
    implementation 'org.greenrobot:eventbus:3.3.1'
}

2).创建一个事件类

这个类的作用是在组件之间传递数据

class MessageEvent(val message: String)

3).注册和注销EventBus

在您想要接收事件的组件(如Activity或Fragment)中,注册和注销EventBus。

override fun onStart() {
    super.onStart()
    EventBus.getDefault().register(this)
}

override fun onStop() {
    super.onStop()
    EventBus.getDefault().unregister(this)
}

4).监听事件

在相同的组件中,添加一个方法来监听事件,这个方法需要用@Subscribe注解。

@Subscribe(threadMode = ThreadMode.MAIN)
public fun onMessageEvent(event: MessageEvent) {
    // 处理事件
    val data = event.message
    // ...处理数据
}

5).发布事件

在需要发送数据的地方,发布一个事件实例。

EventBus.getDefault().post(MessageEvent("Hello, EventBus!"))

6).示例

接收方

class ReceiverActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_receiver)
    }

    override fun onStart() {
        super.onStart()
        EventBus.getDefault().register(this)
    }

    override fun onStop() {
        super.onStop()
        EventBus.getDefault().unregister(this)
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public fun onMessageEvent(event: MessageEvent) {
        // 这里处理接收到的事件
        Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show()
    }
}

发送方

class SenderActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sender)

        // 假设有一个按钮用于发送事件
        val sendButton: Button = findViewById(R.id.sendButton)
        sendButton.setOnClickListener {
            // 当按钮被点击时,发布事件
            EventBus.getDefault().post(MessageEvent("Hello from SenderActivity!"))
        }
    }
}

7.Application 类

1).创建自定义Application类

创建一个新的Kotlin类,继承自Application类,并在该类中定义你想要传递的数据。

class MyApp : Application() {
    var globalData: String? = null
    // 你可以在这里定义更多的变量或方法
}

2).在AndroidManifest.xml中声明

在AndroidManifest.xml文件中的<application>标签内,使用android:name属性来指定你的自定义Application类。

<application
    android:name=".MyApp"
    ...>
    ...
</application>

3).在Activity或其他组件中使用

在任何Activity或其他组件中,你可以通过调用getApplication()方法来获取自定义Application类的实例,并访问其中定义的数据。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        val app = application as MyApp
        app.globalData = "Some data"
    }
}

注意事项

  • 使用Application传递数据时,要注意生命周期,因为当Android系统需要为其他应用释放内存时,它可能会杀死后台进程,这会导致Application对象被重建,数据可能会丢失。

  • 这种方法适合传递少量的、全局需要的数据。如果数据量较大或者需要持久化存储,应该考虑使用数据库、SharedPreferences或其他存储机制。

  • 为了避免内存泄漏,不要在Application类中持有Activity、View或其他上下文相关的引用。

通过这种方式,你可以在不同的组件间共享数据,但要确保对共享数据的访问是线程安全的。

8.Parcelable

Parcelable和Serializable是两种常用的数据传递方式。Parcelable是Android特有的接口,性能比Serializable好,但实现稍微复杂一些。Serializable是Java提供的接口,实现简单,但性能较差。

实现 Parcelable 接口,使对象能够在页面间进行序列化和反序列化传递。

适用于需要传递自定义对象的情况。

1).创建一个数据类,并实现Parcelable接口。

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class User(val name: String, val age: Int) : Parcelable

从Kotlin 1.1.4开始,可以使用@Parcelize注解来自动实现Parcelable接口,前提是在项目的build.gradle文件中启用了kotlin-parcelize插件。

plugins {
    // 其它插件...
    id("org.jetbrains.kotlin.plugin.parcelize") 
}

2).在启动新Activity时,将Parcelable对象放入Intent。

val intent = Intent(this, SecondActivity::class.java).apply {
    val user = User("John Doe", 30)
    putExtra("USER_KEY", user)
}
startActivity(intent)

3).在接收Activity中,从Intent中取出Parcelable对象。

class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)

        val user = intent.getParcelableExtra<User>("USER_KEY")
        user?.let {
            // 使用user对象
        }
    }
}

注意: 当使用Serializable时,所有序列化的对象中的子对象也必须实现Serializable接口。而Parcelable则需要每个子对象都要实现Parcelable接口。

建议在Android中优先使用Parcelable,因为它比Serializable更高效。

9.Serializable

创建一个实现 Serializable 接口的数据类。

在发送页面中创建数据对象,并将其放入 Intent 中。

在接收页面中从 Intent 中获取传递的 Serializable 对象。

1).创建一个数据类,并实现Serializable接口。

import java.io.Serializable

data class User(val name: String, val age: Int) : Serializable

2).在启动新Activity时,将Serializable对象放入Intent。

val intent = Intent(this, SecondActivity::class.java).apply {
    val user = User("John Doe", 30)
    putExtra("USER_KEY", user)
}
startActivity(intent)

3).在接收Activity中,从Intent中取出Serializable对象。

class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)

        val user = intent.getSerializableExtra("USER_KEY") as? User
        user?.let {
            // 使用user对象
        }
    }
}

10.数据库(Database)

使用数据库存储数据,并在不同页面间读取和写入数据。

可以使用 SQLite、Room 等数据库框架进行数据的持久化和共享。

适用于需要长期存储和大量数据共享的情况。

1).添加依赖

在项目的build.gradle文件中,添加Room数据库的依赖。

plugins {
    id("kotlin-kapt")
}

android {
    ...
    defaultConfig {
        ...
        kapt {
            arguments {
                arg("room.schemaLocation", "$projectDir/schemas")
            }
        }
    }
  
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }
    kotlinOptions {
        jvmTarget = "17"
    }
    ...
}
    
dependencies {
    implementation("androidx.room:room-runtime:2.5.0")
    //annotationProcessor("androidx.room:room-compiler:2.5.0")
    // For Kotlin use kapt instead of annotationProcessor
    kapt("androidx.room:room-compiler:2.5.0")
    // optional - Kotlin Extensions and Coroutines support for Room
    implementation("androidx.room:room-ktx:2.5.0")
}

2).定义数据模型

创建一个数据类,并使用@Entity注解标记,表示这是一个数据库表。

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val age: Int
)

3).创建DAO(数据访问对象)

定义一个接口,使用@Dao注解标记,里面包含访问数据库的方法。

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query

@Dao
interface UserDao {
    @Insert
    suspend fun insertUser(user: User): Long

    @Query("SELECT * FROM user WHERE id = :id")
    suspend fun getUserById(id: Int): User?
}

4).创建数据库实例

创建一个抽象类,继承自RoomDatabase,并使用@Database注解。

import androidx.room.Database
import androidx.room.RoomDatabase

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

5).使用数据库

在您的Activity或Fragment中,获取数据库实例并执行数据库操作。

val db = Room.databaseBuilder(
    applicationContext,
    AppDatabase::class.java, "database-name"
).build()

val userDao = db.userDao()

// 插入用户
GlobalScope.launch {
    userDao.insertUser(User(1, "John Doe", 30))// 测试时每次修改一下ID,不然存在相同ID会报错
}

// 查询用户
GlobalScope.launch {
    val user = userDao.getUserById(1)
    // 使用user对象
}

注意:

  • 上述代码中使用了Kotlin协程来处理异步数据库操作。

  • Room.databaseBuilder()需要一个Context对象,通常您会在Activity或Application中调用它。

  • 数据库操作(如插入和查询)不应在主线程上执行,因为它们可能会阻塞UI,所以应该在协程或其他异步机制中运行。

  • GlobalScope的使用在真实的应用程序中并不推荐,因为它的生命周期是整个应用程序,您应该使用具有更短生命周期的作用域,如lifecycleScope或viewModelScope。

11.文件(File)

将数据存储到文件中,在不同页面间通过读写文件来传递数据。

可以使用内部存储或外部存储来创建和访问文件。

适用于大量数据或需要持久化存储的情况。

1).定义一个帮助类或者函数来处理文件的读写操作

以下是一个简单的例子:

import android.content.Context
import java.io.*

class FileHelper(private val context: Context) {

    fun writeToFile(fileName: String, data: String) {
        context.openFileOutput(fileName, Context.MODE_PRIVATE).use { outputStream ->
            outputStream.write(data.toByteArray())
        }
    }

    fun readFromFile(fileName: String): String {
        return context.openFileInput(fileName).bufferedReader().useLines { lines ->
            lines.fold("") { some, text ->
                "$some\n$text"
            }
        }
    }
}

2).在您的Activity或Fragment中,您可以使用这个帮助类来存储数据到文件。

class SomeActivity : AppCompatActivity() {
    private lateinit var fileHelper: FileHelper

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

        fileHelper = FileHelper(this)

        // 保存数据到文件
        val dataToSave = "Some data to be shared"
        fileHelper.writeToFile("shared_data.txt", dataToSave)
    }

    private fun loadData() {
        // 从文件中读取数据
        val data = fileHelper.readFromFile("shared_data.txt")
        // 使用读取的数据
        // ...
    }
}

3).在另一个页面,您可以使用相同的FileHelper实例来读取之前写入的文件。

class AnotherActivity : AppCompatActivity() {
    private lateinit var fileHelper: FileHelper

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

        fileHelper = FileHelper(this)

        // 读取数据
        val sharedData = fileHelper.readFromFile("shared_data.txt")
        // 使用数据
        // ...
    }
}

确保在使用文件进行数据传递时考虑到线程安全和性能问题。对于大量数据或频繁的读写操作,可能需要考虑使用其他数据传递方法,例如数据库或SharedPreferences。此外,对于敏感数据,请确保适当加密,以保护用户数据安全。

12. 网络请求(Network Request)

使用网络请求来传递数据,可以通过 HTTP 请求或其他网络协议进行数据交换。

发送方将数据通过网络发送给接收方,接收方通过解析网络响应来获取数据。

适用于远程数据交换或与服务器进行通信的情况。

1).添加网络权限到你的AndroidManifest.xml文件

<uses-permission android:name="android.permission.INTERNET" />

2).选择一个网络请求库

如Retrofit, OkHttp或Volley,这里以Retrofit为例。

3).添加所选网络库的依赖到你的build.gradle文件中

dependencies {
    // Retrofit & Gson
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
}

4).创建一个模型类来表示你的数据

data class User(val name: String, val email: String)

5).定义一个接口来描述HTTP请求

import retrofit2.Call
import retrofit2.http.GET

interface ApiService {
    @GET("users/info")
    fun getUserInfo(): Call<User>
}

6).使用Retrofit构建器实例化你的服务

import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object RetrofitClient {
    private const val BASE_URL = "https://your.api.url/"

    val apiService: ApiService by lazy {
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(ApiService::class.java)
    }
}

7).发送网络请求并处理响应

import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class MainActivity : AppCompatActivity() {

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

        RetrofitClient.apiService.getUserInfo().enqueue(object : Callback<User> {
            override fun onResponse(call: Call<User>, response: Response<User>) {
                if (response.isSuccessful) {
                    val userInfo = response.body()
                    // 使用userInfo数据
                }
            }

            override fun onFailure(call: Call<User>, t: Throwable) {
                // 处理请求失败的情况
            }
        })
    }
}

13.ContentProvider

使用 ContentProvider 进行跨应用的数据共享和传递。

ContentProvider 提供了标准的接口和方法来操作数据,并可以通过 URI 进行数据的访问。

适用于需要在不同应用间共享数据的情况。

1).定义一个ContentProvider类

首先,创建一个类继承自ContentProvider并实现它的抽象方法。

class MyContentProvider : ContentProvider() {

    // 初始化ContentProvider
    override fun onCreate(): Boolean {
        // 初始化数据库等操作
        return true
    }

    // 查询数据
    override fun query(
        uri: Uri,
        projection: Array<String>?,
        selection: String?,
        selectionArgs: Array<String>?,
        sortOrder: String?
    ): Cursor? {
        // 处理查询请求
        return null
    }

    // 插入数据
    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        // 处理插入请求
        return null
    }

    // 更新数据
    override fun update(
        uri: Uri,
        values: ContentValues?,
        selection: String?,
        selectionArgs: Array<String>?
    ): Int {
        // 处理更新请求
        return 0
    }

    // 删除数据
    override fun delete(
        uri: Uri,
        selection: String?,
        selectionArgs: Array<String>?
    ): Int {
        // 处理删除请求
        return 0
    }

    // 返回MIME类型
    override fun getType(uri: Uri): String? {
        // 根据URI返回正确的MIME类型
        return null
    }
}

2).在AndroidManifest.xml中注册ContentProvider

<provider
    android:name=".MyContentProvider"
    android:authorities="com.example.myapp.provider"
    android:exported="true" />

android:authorities应该是唯一的,通常使用应用的包名作为前缀。

3).使用ContentResolver访问ContentProvider

其他应用可以使用ContentResolver来查询你的ContentProvider。

获取ContentResolver实例:

在你的应用中,你可以通过调用getContentResolver()方法来获取ContentResolver的实例。这通常在Activity或Service中进行。

val contentResolver = context.contentResolver

构建URI:

访问ContentProvider的数据时,你需要指定一个URI。这个URI指向你想要访问的数据集合或单个数据项。URI通常遵循这样的格式:content://<authority>/<path>,其中<authority>是在AndroidManifest.xml中注册ContentProvider时指定的,并且是唯一的。<path>是你希望访问的数据表或数据类型。

val uri: Uri = Uri.parse("content://com.example.myapp.provider/table_name")

查询数据:

使用ContentResolver的query()方法来请求数据。你可以指定列名、选择条件、选择参数和排序顺序。

val cursor: Cursor? = contentResolver.query(
    uri,
    projection, // String数组,代表你想要返回的列。
    selection, // SQL中的where子句,但不包括"WHERE"本身。
    selectionArgs, // 与selection中的占位符相匹配的值。
    sortOrder // 结果的排序方式。
)

处理返回的Cursor:

如果查询成功,query()方法将返回一个Cursor对象。通过这个Cursor,你可以遍历和读取数据。

cursor?.let {
    while (it.moveToNext()) {
        // 使用Cursor获取数据
        val columnValue = it.getString(it.getColumnIndex("column_name"))
        // 处理数据...
    }
}
cursor?.close() // 最后记得关闭Cursor

插入、更新和删除数据:

除了查询数据,ContentResolver还提供了insert(), update(), 和 delete()方法来进行数据的增、改、查操作。

// 插入数据
val newUri: Uri? = contentResolver.insert(uri, contentValues)

// 更新数据
val rowsUpdated: Int = contentResolver.update(uri, contentValues, selection, selectionArgs)

// 删除数据
val rowsDeleted: Int = contentResolver.delete(uri, selection, selectionArgs)

处理权限:

如果ContentProvider包含私有数据或者需要限制访问,你需要在AndroidManifest.xml中声明相应的权限,并在访问时请求这些权限。

安全性考虑:

当你的ContentProvider向其他应用公开数据时,需要考虑到数据安全性。确保对输入的URI进行验证,避免SQL注入等安全漏洞,并根据需要对访问进行身份验证和授权。

通过这种方式,ContentResolver和ContentProvider一起提供了一种强大的机制,允许应用之间安全、高效地共享数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/191748.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

redis key

不管是&#xff1a;规则&#xff0c;还是其他规则&#xff0c;定义好就可以了。其实没有太多要求的。 1&#xff09;冒号分割类似那种yaml在客户端显示树结构 2&#xff09;其他分割类似那种properties在客户端显示列表结构

数组栈的实现

1.栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作 进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底 栈中的数据元素遵守后进先出LIFO,&#xff08;Last In First Out&#xff09;的原则 压栈&…

【赠书第8期】工程效能十日谈

文章目录 前言 1 工程效能十日谈 1.1 制定清晰的目标和计划 1.2 引入先进的技术和工具 1.3 建立有效的沟通机制 1.4 灵活应对变化 1.5 确保资源充足 1.6 进行有效的风险管理 1.7 进行持续的监控和评估 1.8 优化团队合作 1.9 注重质量管理 1.10 进行项目总结和反思 …

PyEcharts-Faker的介绍

1 PyEcharts-Faker from pyecharts.faker import Faker方法属性说明对应内容Faker.clothes[“衬衫”, “毛衣”, “领带”, “裤子”, “风衣”, “高跟鞋”, “袜子”]Faker.values()[106, 111, 145, 33, 20, 138, 141]Faker.drinks[“可乐”, “雪碧”, “橙汁”, “绿茶”,…

【管理运筹学】背诵手册(六)| 图与网络分析(基本概念、最小支撑树问题、最短路问题)

六、图与网络分析 基本概念、术语 某个边的两个端点相同&#xff0c;称为环&#xff1b;两点之间有多于一条的边&#xff0c;成为多重边。一个无环、无多重边的图称为简单图&#xff0c;无环但允许有多重边的图称为多重图。 次&#xff1a;以 v i v_i vi​ 为端点的边的数目…

Redis序列化操作

目录 1.protostuff 的 Maven 依赖 2.定义实体类 3.序列化工具类 ProtostuffSerializer 提供了序列化和反序列化方法 4.测试 利用 Jedis 提供的字节数组参数方法&#xff0c;如&#xff1a; public String set(String key, String value) public String set(byte[] key…

IDEA DeBug

文章目录 01_Debug简介和意义02_IDEA中的Debug步骤03_跳转到当前代码执行的行04_步过调试的使用05_步入调试的使用06_强制步入调试的使用07_步出调试的使用08_回退断点调试的使用09_运行到光标处10_计算表达式11_条件断点12_多线程调试 01_Debug简介和意义 什么是程序DeBug&am…

人力资源管理后台 === 主页模块

目录 1.获取用户资料在Vuex中共享 2.显示用户头像和用户名 3.处理头像为空的场景 4.处理token失效的问题 5.调整下拉菜单&#xff0c;实现退出登录 6.修改密码功能实现 6.1-修改密码-弹出层 6.2-修改密码-表单结构 6.3-修改密码-表单校验 6.4-修改密码-确定和取消 7.…

设计模式精讲:掌握单例模式的实现与优化

掌握单例模式的实现与优化 一、引言&#xff1a;如何学习设计模式&#xff1f;二、前置知识&#xff1a;对象的创建的销毁2.1、拷贝构造2.2、拷贝赋值构造2.3、移动构造2.4、移动赋值构造 三、单例模式的定义四、单例模式的实现与优化4.1、版本一4.2、版本二4.3、版本三4.4、版…

均匀球形分布的随机三维单位向量

生成具有均匀球形分布的随机三维单位向量[参考] import numpy as np import matplotlib.pyplot as plt def random_three_vector():"""Generates a random 3D unit vector (direction) with a uniform spherical distributionAlgo from http://stackoverflow.c…

论文阅读:C2VIR-SLAM: Centralized Collaborative Visual-Inertial-Range SLAM

前言 论文全程为C2VIR-SLAM: Centralized Collaborative Visual-Inertial-Range Simultaneous Localization and Mapping&#xff0c;是发表在MDPI drones&#xff08;二区&#xff0c;IF4.8&#xff09;上的一篇论文。这篇文章使用单目相机、惯性测量单元( IMU )和UWB设备作为…

Node——npm包管理器的使用

Node.js使用npm对包进行管理&#xff0c;其全称为Node Package Manager&#xff0c;开发人员可以使用它安装、更新或者卸载Node.js的模块 1、npm包管理器基础 1.1、npm概述 npm是Node.js的标准软件包管理器&#xff0c;其在2020年3月17日被GitHub收购&#xff0c;而且保证永…

1.9 字符数组

1.9 字符数组 一、字符数组概述二、练习 一、字符数组概述 所谓字符数组&#xff0c;就是char类型的数组&#xff0c;比如 char a[]&#xff0c;是C语言中最常用的数组类型&#xff0c;先看一个程序 #include <stdio.h> #define MAXLINE 1000 //最大行长度限制 int get…

软件介绍02- flameshot截图软件(linux系统可用)

1 软件介绍 在Windows和mac平台一直都使用着snipaste截图&#xff0c;非常好用&#xff0c;又能够钉图。遗憾是并没有开发linux版本&#xff0c;真不知道为什么。 好在终于找到一款截图软件&#xff0c;flameshot截图软件&#xff0c;可以平替snipaste。 下载网址&#xff1a;…

什么是好的FPGA编码风格?(3)--尽量不要使用锁存器Latch

前言 在FPGA设计中&#xff0c;几乎没人会主动使用锁存器Latch&#xff0c;但有时候不知不觉中你的设计莫名其妙地就生成了一堆Latch&#xff0c;而这些Latch可能会给你带来巨大的麻烦。 什么是锁存器Latch&#xff1f; Latch&#xff0c;锁存器&#xff0c;一种可以存储电路…

【Linux】进程间通信

进程间通信 1. 进程间通信介绍1.1 进程间通信目的1.2 进程间通信发展1.3 进程间通信分类1.4 进程间通信的本质理解 2. 管道3. 匿名管道3.1 pipe()函数3.2 站在文件描述符角度-深度理解管道3.3 站在内核角度-管道本质3.4 匿名管道使用步骤3.4 管道读写规则3.5 管道的读与写的五种…

复数的乘幂与方根

1、乘积与商 设 几何意义&#xff1a; &#xff1a;逆时针旋转一个角度&#xff0c;并伸长倍 &#xff1a;顺时针旋转一个角度&#xff0c;并伸长倍 *特别&#xff1a;不存在 :对实行了一次旋转变换&#xff0c;且长度不变&#xff0c;旋转角为 例题&#xff1a; 2、幂与…

windows下docker环境搭建与运行实战

背景 学习docker使用&#xff0c;需要环境&#xff0c;今天主要的目标是在windows环境下安装docker环境。 为什么要这么搞&#xff0c;主要是企业内部服务器&#xff0c;都是跟公网隔离的&#xff0c;没有访问公网权限&#xff0c;所以镜像什么的&#xff0c;从公网拉取完全没…

MySQL的undo log 与MVCC

文章目录 概要一、undo日志1.undo日志的作用2.undo日志的格式3. 事务id&#xff08;trx_id&#xff09; 二、MVCC1.版本链2.ReadView3.REPEATABLE READ —— 在第一次读取数据时生成一个ReadView4.快照读与当前读 小结 概要 Undo Log&#xff1a;数据库事务开始之前&#xff0…

qt-C++笔记之不使用ui文件纯C++构建时控件在布局管理器作用下的默认位置和大小实践

qt-C笔记之不使用ui文件纯C构建时控件在布局管理器作用下的默认位置和大小实践 code review! 文章目录 qt-C笔记之不使用ui文件纯C构建时控件在布局管理器作用下的默认位置和大小实践1.ChatGPT解释2.ChatGPT——resize()和move()详解3.默认大小和位置——示例运行一4.默认大小…
最新文章