我们是一群法国学生。我们正在开发一种需要数据库的游戏。为简化代码,我们使用LibGdx。 但是,似乎Sugar ORM不受应用程序的约束。我们无法扩展SugarRecord。
我放了AndroidManifest.xml和build.gradle(Module:Android)的代码。我们如何解决这个问题呢?
编辑:我们在Android文件夹中创建我们的类。 Sugar Orm没有在核心中定义。
<application
android:name="com.orm.SugarApp"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/GdxTheme">
<meta-data
android:name="DATABASE"
android:value="AppName.db" />
<meta-data
android:name="VERSION"
android:value="1" />
<meta-data
android:name="QUERY_LOG"
android:value="true" />
<meta-data
android:name="DOMAIN_PACKAGE_NAME"
android:value="com.AppName" />
build.gradle(模块:Android):
dependencies {
compile 'com.github.satyan:sugar:1.3'
//other dependencies
}
谢谢!
答案 0 :(得分:0)
的Bonjour!我将做出一些假设(如果他们错了,请纠正我,我们将在下面提炼答案):
SugarRecord<T>
,而您的编译器/ IDE无法看到该类。SugarRecord<T>
的课程位于core/src/...
,而不是android/src/...
当您编写软件时(如果它的游戏无关紧要),您需要注意如何将软件划分为多个部分以及这些部分如何交互。特别是,您希望能够知道对一个部件的更改何时会破坏另一个部件。
libGDX将其代码分为基于平台的部分(这就是为什么你有核心项目和桌面项目和 android 项目)。 核心应该具有与平台无关的所有代码(即,无论您是在PC还是移动设备上,这些内容都是相同的),而您的其他项目则负责平台特定的东西。
Sugar ORM是一个特定于Android的东西,所以你(正确地)将它放入你的 android gradle项目依赖项中。但是,这意味着只有android/src
文件夹下的代码才能了解Sugar ORM并且可以使用它。我非常确定导致您出现问题的原因。问题是,您要保存的类几乎肯定在core/src
下,并且属于,那么我们如何解决?
如果您只打算让您的程序在Android上运行(并且您的项目有一个紧迫的截止日期:wink :),您可以将依赖项从Android gradle项目移动到Core gradle项目。这将允许您在任何地方使用这些类,但是当您尝试构建Desktop / iOS / HTML项目时,这将意味着麻烦。
如果你想以正确的方式修复它(并且可能会给你的教授留下令人难以置信的编码能力),你需要使用一种叫做依赖注入的东西。依赖注入是指我们采用代码所需的东西,并在运行时将它提供给代码。这意味着我们可以动态决定是否通过 android 数据库或 iOS 数据库。就像@ Arctic45在评论中所说的那样,libGDX Wiki对这种技术有一个简要的概述,但我们会详细介绍一下。
对于这个例子,我将假设一个Monster
类的简单游戏,看起来像这样:
// Lives in core
public class Monster {
public String name; // prénom
public int hitpoints; // points de dommage
public Monster() {
this.name = "Tim the Unnamed";
this.hitpoints = 1;
}
public Monster(String name, int hitpoints) {
this.name = name;
this.hitpoints = hitpoints;
}
@Override
public String toString() {
return String.format("{name: '%s', hitpoints: %n}", this.name, this.hitpoints);
}
public void attack(Monster other) {
// Game specific logic...
}
}
现在我们希望能够将其保存到数据库中,但我们不知道它是Android数据库还是iOS数据库,甚至可能是数据库的数据库在某个地方(如Firebase)。我们如何处理?
我们所做的是为核心提供DatabaseWrapper
界面。这个界面提供了我们需要的方法,但没有包括它们如何实现 - 它就像一个承诺。 核心可以计划使用这些方法,然后一旦我们知道我们所处的平台,我们就会提供它们。以下是一个示例应用程序,它说明了这种技术:
// Lives in core
// Replace with your application
public class LibGDXTestbed extends ApplicationAdapter {
DatabaseWrapper database;
public LibGDXTestbed() { } // For platforms that don't have databases to inject.
public LibGDXTestbed(DatabaseWrapper database) {
this.database = database;
}
/**
* For demo purposes, add a new randomized monster to the database, then log a list of all the
* monsters created to date.
*/
@Override
public void create () {
if(database != null) {
createMonster();
printMonsters();
} else {
Gdx.app.error("WARNING", "No database provided. Load/Save Functionality Disabled.");
}
}
// Helper method
private void createMonster() {
// Create a set of names we can use for new monsters.
String[] names = {"Fred", "Mary", "Jean", "Tim"};
String randomName = new Array<String>(names).random();
int randomHP = MathUtils.random(100);
database.saveMonster(new Monster(randomName, randomHP));
}
// Helper method
private void printMonsters() {
for(Monster monster : database.getMonsters()) {
Gdx.app.log("DEBUG", monster.toString());
}
}
}
请注意,上述内容并不了解有关Sugar ORM的任何信息,也无法对数据库的工作方式做出任何假设。
包装器本身看起来像这样:
// Located in core
public interface DatabaseWrapper {
public void saveMonster(Monster monster);
public List<Monster> getMonsters();
}
现在这有点人为(并且可以重构为更通用),但它说明了这一点。
接下来,我们创建实现此数据库所需的特定于android的代码。首先,我们将创建一个SugarMonster
类,其扩展为SugarRecord
(因为我们不希望使用我们的核心Monster
类本身):
// Lives in android/src
public class SugarMonster extends SugarRecord<SugarMonster> {
public String name; // prénom
public int hitpoints; // points de dommage
public SugarMonster() {
}
public SugarMonster(Monster monster) {
this.name = monster.name;
this.hitpoints = monster.hitpoints;
}
}
我们还需要一个SugarWrapper
类,它在幕后使用Sugar ORM实现我们的DatabaseWrapper
类:
// Lives in android/src
public class SugarWrapper implements DatabaseWrapper {
@Override
public void saveMonster(Monster monster) {
SugarMonster data = new SugarMonster(monster);
data.save();
}
@Override
public List<Monster> getMonsters() {
List<SugarMonster> records = SugarMonster.listAll(SugarMonster.class);
ArrayList<Monster> monsters = new ArrayList<>();
for(SugarMonster record : records) {
monsters.add(new Monster(record.name, record.hitpoints));
}
return monsters;
}
}
最后,我们需要更新我们的AndroidLauncher
类以注入我们的数据库包装器:
// Lives in android/src
public class AndroidLauncher extends AndroidApplication {
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
initialize(new LibGDXTestbed(new SugarWrapper()), config);
}
}
另一个很酷的事情是,如果你实施这个&#34;对&#34;方式,它为测试提供了一些很酷的可能性。如果要针对代码编写单元测试,可以创建TestWrapper
来实现DatabaseWrapper
并使用静态数据模拟数据库功能:
public class TestWrapper implements DatabaseWrapper {
List<Monster> monsters;
public TestWrapper() {
this.monsters = new ArrayList<>();
this.monsters.add(new Monster("Tim the Tester", 123));
}
@Override
public void saveMonster(Monster monster) {
this.monsters.add(monster);
}
@Override
public List<Monster> getMonsters() {
return this.monsters;
}
}