parse.com - 嵌套查询和加入 Table
parse.com - Nested query and Join Table
我对嵌套查询有疑问。在 query5.whereEqualTo("piwo", followList2.get(0))
中,我想获取该对象,但它吐出错误,指出 followList2 需要声明为最终的,但是当它执行时,所有匿名 class 都变成红色并出现 Cannot resolve constructor(...)
错误。有人以前收到过这个吗?
ParseQuery<ParseObject> query3 = ParseQuery.getQuery("Piwo");
query3.whereEqualTo("marka", beer); // TODO if(beer == "all") then don't use it
query3.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> followList2, ParseException e) {
if (followList2 != null) {
Log.d("ASD", "Szukane piwo: " + followList2.get(0).getString("marka"));
} else {
Log.d("ASD", "Zero wyników1");
}
ParseQueryAdapter<ParseObject> adapter =
new ParseQueryAdapter<ParseObject>(this, new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery<ParseObject> create() {
// Here we can configure a ParseQuery to our heart's desire.
ParseQuery query5 = new ParseQuery("Cena");
query5.whereContainedIn("lokal", list);
query5.whereEqualTo("piwo", followList2.get(0);
query5.include("piwo");
query5.include("lokal");
query5.orderByAscending("cena");
return query5;
}
});
adapter.setTextKey("lokal.place");
adapter.setImageKey("photo");
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
如果我没理解错的话,你已经尝试过了:
...
public void done(final List<ParseObject> followList2, ParseException e) {
...
由于某种原因,这让编译器不高兴。
我认为可能有两种可能的解决方案
- 如果您打算在 Activity/Fragment 的其他地方使用 followList2 对象。然后简单地声明一个字段变量来保存结果并从中读取。这样匿名内部 class 应该可以访问它。
- 将 followList2 写入另一个声明为 final 的局部变量。这样我们就不会改变 done() 回调的签名。
解决方案 1:
List<ParseObject> mFollowList2; // field variable outside method
...
public void done(List<ParseObject> followList2, ParseException e) {
mFollowList2 = followList2;
// use mFollowList2 in rest of code
...
解决方案 2:
public void done(List<ParseObject> followList2, ParseException e) {
final List<ParseObject> finalFollowList2 = followList2;
// use finalFollowList2 in rest of code
...
正如评论中所说,我不记得有过同样的问题,但我希望这能解决问题。
第三个建议是试用 Bolts https://github.com/BoltsFramework/Bolts-Android(附带解析 API)。如果您熟悉 javascript 中的 Promise,Bolts 与 Java 中的 Promise 基本相同。它消除了嵌套调用的需要,随着依赖查询数量的增长,形成金字塔形的代码块。然而,它确实需要一些时间来适应,在简单的情况下是没有必要的。
奖金:
由于您在使用适配器中包含的文本时遇到问题,我将向您展示我的一些代码作为示例。
首先,我有一个简单的项目布局:
res/layout/view_adapter_item_simple.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="?android:attr/activatedBackgroundIndicator"
android:paddingTop="5dp">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="item" />
</RelativeLayout>
接下来,这是我的自定义适配器:
public class SimpleParseAdapter<T extends ParseObject> extends
ParseQueryAdapter<T> {
private static final String TAG = SimpleParseAdapter.class.getSimpleName();
private final String textCol;
public SimpleParseAdapter(Context context, String textCol,
QueryFactory<T> queryFactory) {
super(context, queryFactory);
this.textCol = textCol;
}
TextView text;
@Override
public View getItemView(T object, View v, ViewGroup parent) {
if (v == null) {
v = View.inflate(getContext(), R.layout.view_adapter_item_simple,
null);
}
super.getItemView(object, v, parent);
text = (TextView) v.findViewById(R.id.text);
text.setText(object.getString(textCol));
return v;
}
}
注意:我们还没有完成。这与标准的 ParseQueryAdapter 类似,因为它只使用 text.setText(object.getString(textCol))
.
查看当前 class 的列
但是,可以很容易地编写一个专用适配器来处理嵌套包含,例如:
public class SimpleParseIncludeAdapter<T extends ParseObject> extends
ParseQueryAdapter<T> {
private static final String TAG = SimpleParseIncludeAdapter.class.getSimpleName();
private final String includeCol;
private final String textCol;
public SimpleParseIncludeAdapter(Context context, String includeCol, String textCol,
QueryFactory<T> queryFactory) {
super(context, queryFactory);
this.includeCol = includeCol;
this.textCol = textCol;
}
TextView text;
@Override
public View getItemView(T object, View v, ViewGroup parent) {
if (v == null) {
v = View.inflate(getContext(), R.layout.view_adapter_item_simple,
null);
}
super.getItemView(object, v, parent);
text = (TextView) v.findViewById(R.id.text);
text.setText(object.getParseObject(includeCol).getString(textCol));
return v;
}
}
现在像这样使用适配器:
new SimpleParseIncludeAdapter(**context**, "lokal", "place",**queryFactory**);
其中 queryFactory 有义务做 query.include("lokal")
(包括整个 'lokal' 指针),或`query.include("lokal.place")(仅包括 'place' 列 'lokal');
额外奖励 - subclassing
最后一点,您似乎没有使用 subclassing,但如果您使用了,您也可以为 Cena subclasses 提供专门的自定义适配器。
public class CenaParseAdapter extends
ParseQueryAdapter<Cena> {
private static final String TAG = CenaParseAdapter.class.getSimpleName();
public CenaParseAdapter(Context context,
QueryFactory<Cena> queryFactory) {
super(context, queryFactory);
}
TextView text;
@Override
public View getItemView(Cena cena, View v, ViewGroup parent) {
if (v == null) {
v = View.inflate(getContext(), R.layout.view_adapter_item_simple,
null);
}
super.getItemView(object, v, parent);
text = (TextView) v.findViewById(R.id.text);
text.setText(cena.getPlace());
return v;
}
}
在这种情况下 cena.getPlace()
可以查找包含的本地:
// inside Cena sublass
public Lokal getLokal() { // assuming Lokal also is subclassed
return (Lokal)getParseObject("lokal");
}
public String getPlace() {
return (getLokal() != null) ? getLokal().getPlace() : "";
}
// inside Lokal subclass
public String getPlace() {
return getString("place");
}
我对嵌套查询有疑问。在 query5.whereEqualTo("piwo", followList2.get(0))
中,我想获取该对象,但它吐出错误,指出 followList2 需要声明为最终的,但是当它执行时,所有匿名 class 都变成红色并出现 Cannot resolve constructor(...)
错误。有人以前收到过这个吗?
ParseQuery<ParseObject> query3 = ParseQuery.getQuery("Piwo");
query3.whereEqualTo("marka", beer); // TODO if(beer == "all") then don't use it
query3.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> followList2, ParseException e) {
if (followList2 != null) {
Log.d("ASD", "Szukane piwo: " + followList2.get(0).getString("marka"));
} else {
Log.d("ASD", "Zero wyników1");
}
ParseQueryAdapter<ParseObject> adapter =
new ParseQueryAdapter<ParseObject>(this, new ParseQueryAdapter.QueryFactory<ParseObject>() {
public ParseQuery<ParseObject> create() {
// Here we can configure a ParseQuery to our heart's desire.
ParseQuery query5 = new ParseQuery("Cena");
query5.whereContainedIn("lokal", list);
query5.whereEqualTo("piwo", followList2.get(0);
query5.include("piwo");
query5.include("lokal");
query5.orderByAscending("cena");
return query5;
}
});
adapter.setTextKey("lokal.place");
adapter.setImageKey("photo");
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
如果我没理解错的话,你已经尝试过了:
...
public void done(final List<ParseObject> followList2, ParseException e) {
...
由于某种原因,这让编译器不高兴。
我认为可能有两种可能的解决方案
- 如果您打算在 Activity/Fragment 的其他地方使用 followList2 对象。然后简单地声明一个字段变量来保存结果并从中读取。这样匿名内部 class 应该可以访问它。
- 将 followList2 写入另一个声明为 final 的局部变量。这样我们就不会改变 done() 回调的签名。
解决方案 1:
List<ParseObject> mFollowList2; // field variable outside method
...
public void done(List<ParseObject> followList2, ParseException e) {
mFollowList2 = followList2;
// use mFollowList2 in rest of code
...
解决方案 2:
public void done(List<ParseObject> followList2, ParseException e) {
final List<ParseObject> finalFollowList2 = followList2;
// use finalFollowList2 in rest of code
...
正如评论中所说,我不记得有过同样的问题,但我希望这能解决问题。
第三个建议是试用 Bolts https://github.com/BoltsFramework/Bolts-Android(附带解析 API)。如果您熟悉 javascript 中的 Promise,Bolts 与 Java 中的 Promise 基本相同。它消除了嵌套调用的需要,随着依赖查询数量的增长,形成金字塔形的代码块。然而,它确实需要一些时间来适应,在简单的情况下是没有必要的。
奖金:
由于您在使用适配器中包含的文本时遇到问题,我将向您展示我的一些代码作为示例。
首先,我有一个简单的项目布局:
res/layout/view_adapter_item_simple.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="?android:attr/activatedBackgroundIndicator"
android:paddingTop="5dp">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="item" />
</RelativeLayout>
接下来,这是我的自定义适配器:
public class SimpleParseAdapter<T extends ParseObject> extends
ParseQueryAdapter<T> {
private static final String TAG = SimpleParseAdapter.class.getSimpleName();
private final String textCol;
public SimpleParseAdapter(Context context, String textCol,
QueryFactory<T> queryFactory) {
super(context, queryFactory);
this.textCol = textCol;
}
TextView text;
@Override
public View getItemView(T object, View v, ViewGroup parent) {
if (v == null) {
v = View.inflate(getContext(), R.layout.view_adapter_item_simple,
null);
}
super.getItemView(object, v, parent);
text = (TextView) v.findViewById(R.id.text);
text.setText(object.getString(textCol));
return v;
}
}
注意:我们还没有完成。这与标准的 ParseQueryAdapter 类似,因为它只使用 text.setText(object.getString(textCol))
.
但是,可以很容易地编写一个专用适配器来处理嵌套包含,例如:
public class SimpleParseIncludeAdapter<T extends ParseObject> extends
ParseQueryAdapter<T> {
private static final String TAG = SimpleParseIncludeAdapter.class.getSimpleName();
private final String includeCol;
private final String textCol;
public SimpleParseIncludeAdapter(Context context, String includeCol, String textCol,
QueryFactory<T> queryFactory) {
super(context, queryFactory);
this.includeCol = includeCol;
this.textCol = textCol;
}
TextView text;
@Override
public View getItemView(T object, View v, ViewGroup parent) {
if (v == null) {
v = View.inflate(getContext(), R.layout.view_adapter_item_simple,
null);
}
super.getItemView(object, v, parent);
text = (TextView) v.findViewById(R.id.text);
text.setText(object.getParseObject(includeCol).getString(textCol));
return v;
}
}
现在像这样使用适配器:
new SimpleParseIncludeAdapter(**context**, "lokal", "place",**queryFactory**);
其中 queryFactory 有义务做 query.include("lokal")
(包括整个 'lokal' 指针),或`query.include("lokal.place")(仅包括 'place' 列 'lokal');
额外奖励 - subclassing
最后一点,您似乎没有使用 subclassing,但如果您使用了,您也可以为 Cena subclasses 提供专门的自定义适配器。
public class CenaParseAdapter extends
ParseQueryAdapter<Cena> {
private static final String TAG = CenaParseAdapter.class.getSimpleName();
public CenaParseAdapter(Context context,
QueryFactory<Cena> queryFactory) {
super(context, queryFactory);
}
TextView text;
@Override
public View getItemView(Cena cena, View v, ViewGroup parent) {
if (v == null) {
v = View.inflate(getContext(), R.layout.view_adapter_item_simple,
null);
}
super.getItemView(object, v, parent);
text = (TextView) v.findViewById(R.id.text);
text.setText(cena.getPlace());
return v;
}
}
在这种情况下 cena.getPlace()
可以查找包含的本地:
// inside Cena sublass
public Lokal getLokal() { // assuming Lokal also is subclassed
return (Lokal)getParseObject("lokal");
}
public String getPlace() {
return (getLokal() != null) ? getLokal().getPlace() : "";
}
// inside Lokal subclass
public String getPlace() {
return getString("place");
}