【问题标题】:How can I update my Android SQLite database from a thread without access to the Context?如何在不访问上下文的情况下从线程更新我的 Android SQLite 数据库?
【发布时间】:2016-05-11 20:59:14
【问题描述】:

我正在开发一个 Android 应用程序。应用程序在启动时要做的第一件事就是启动一个监听线程。此侦听线程打开一个 UDP 套接字到平板电脑上的另一个应用程序,并侦听该其他应用程序以发送数据。当我的监听线程接收到数据时,我想将数据存储到 SQLite 数据库中,但是如果不访问我的应用程序的上下文,我无法弄清楚如何做到这一点。

我有一个数据库助手应用:

public class DatabaseHelper extends SQLiteOpenHelper {
    public DatabaseHelper(Context context){
        super(context, "myAppDatabase.db", null, 1);
    }

    @Override
    public void OnCreate(SQLiteDatabase db){
        db.execSQL("CREATE TABLE ...");
    }

    @Override
    public void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
        db.execSQL("DROP TABLE ...");
    }

    // my database CRUD queries
}

这个 DatabaseHelper 类是我对数据库执行任何 CRUD 操作的唯一地方。

我从 MainActivity 开始我的线程:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState){
        ListenerClass myListenerClass = new ListenerClass();
        Thread listenerThread = new Thread(myListenerClass);
        listenerThread.setName("My Listener Thread");
        listenerThread.start();
    }
}

我有我的监听类:

public class ListenerClass implements Runnable {
    private volatile boolean run = true;
    private DataProcessingClass myDataProcessingClass;

    @Override
    public void run(){
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
        // Open UDP socket
        // Listen for data
        // Process the data
        myDatagramSocket.receive(myDatagramPacket);
        byte[] data = myDatagramPacket.getData();
        myDataProcessingClass = new DataProcessingClass();
        myDataProcessingClass.processData(data);
    }

    public void setRun(boolean run){
        this.run = run;
    }
}

当我的侦听器线程接收到数据时,它会调用另一个类来处理该数据,并将其存储到数据库中。在我尝试将其存储到数据库之前它一直有效,因为我无权访问应用程序的上下文。

有没有办法在不访问应用程序上下文的情况下写入 SQLite 数据库?如果没有,我该如何获取这个数据库写入的上下文?

【问题讨论】:

  • 一种解决方案是添加一个构造函数,该构造函数接受要使用的上下文。您需要对所有需要上下文的类执行此操作,包括那些简单地将上下文传递给另一个类的类。
  • 我也想过,但好像不是很干净。当然有一种方法可以更干净地做到这一点。

标签: java android multithreading sqlite


【解决方案1】:

很遗憾,如果没有Context 的访问权限,我认为您将无法执行此操作。

在这个方向上我能给你的唯一建议是引入 Context 作为线程的依赖项。

我还想指出一些与架构相关的其他事情。在一般情况下,您的方法对于应用间通信是完全有效的,但我认为在 Android 方面它有点不理想。

您可以通过多种方式利用开箱即用的组件为您完成繁重的工作。我建议您使用ContentProviders - 它们非常适合在应用程序之间共享数据,并且无需 UDP 连接、处理线程并大大简化您的应用程序架构。

另一种选择是使用Intent 机制 - 您可以让应用 A 向应用 B 发送带有二进制数据的意图。应用 B 可以处理广播接收器中的意图,这将使您可以访问 Context 和调用应用程序其他组件的能力,能够持久化结果数据。

【讨论】:

  • +1 提及ContentProviders。这实际上可能是 OP 比使用 UDP 更好的解决方案。
  • 唯一的事情是,我必须通过 UDP 与其他应用程序通信。另一个应用程序是通过 Xamarin 移植到 Android 的 Windows C# 应用程序。它是内部的,我必须使用它。我将尝试像您建议的那样“将上下文作为线程的依赖项引入”。关于在哪里寻找这方面的例子有什么建议吗?附带说明一下,如果没有某种挂钩到主应用程序,后台进程无法访问后台数据库是非常疯狂的。有点违背了 MVC 分离的目的。
  • 引入Context 作为依赖项基本上就是@Code-Apprentice 在他的回答中指出的。至于修改数据库时有Context 的必要性,我猜这是Android 安全模型的结果。问题是直接使用Threads 在Android 中被认为是非常低级的,因为该平台提供了其他实用程序来帮助处理多线程。您可以尝试将您的逻辑从线程迁移到IntentService。它基本上可以满足您的需求,并为您提供可用于数据库更新的Context
  • @Brian “有点违背了 MVC 分离的目的。”我不同意。访问隔离到单个类的系统资源支持 MVC 分离。
【解决方案2】:

我通常使用的解决方案是添加一个采用Context 的构造函数。在这种特殊情况下,您需要将这样的构造函数添加到ListenerClassDataProcessingClassListenerClass 构造函数会将给定的Context 传递给DataProcessingClass 构造函数。

或者,您可以像以前一样添加 DataProcessingClass(Context) 构造函数,但改为使用 ListenerClass(DataProcessingClass) 构造函数。这允许其他人首先初始化DataProcessingClass 对象,这样ListenerClass 就不必担心它是如何初始化的。此外,这允许您更进一步并使用依赖注入来初始化您的对象。 (对于这个问题,依赖注入可能是一个比必要的更高级的主题。我只想提一下,如果您有兴趣可以进一步研究。)

【讨论】:

    【解决方案3】:

    您可以继承Application 并提供静态方法来获取应用上下文:

    public class MyApplication extends Application {
        private static Context sContext;
    
        public static Context getContext() {
            return sContext;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            sContext = this;
        }
    }
    

    启动应用程序时,系统会构造Application 实例并调用其onCreate(),然后再创建任何活动、服务或接收器(请参阅文档中的cmets 以获取Application.onCreate())。因此,活动代码可以依赖 MyApplication.getContext() 始终返回有效的上下文。

    如果您使用这种方法,请记住还要更新清单中的应用程序名称:

    <application
        ...
        android:name="com.example.MyApplication" >
    

    【讨论】:

      猜你喜欢
      • 2013-04-15
      • 2018-01-05
      • 2018-07-06
      • 1970-01-01
      • 2018-10-02
      • 1970-01-01
      • 2021-02-16
      • 1970-01-01
      相关资源
      最近更新 更多