parse.com — вложенный запрос и таблица соединения

У меня проблема с вложенным запросом. В query5.whereEqualTo("piwo", followList2.get(0)) я хочу получить объект, но он выдает ошибку, что followList2 должен быть объявлен окончательным, но когда это происходит, весь анонимный класс становится красным с ошибкой 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);

person jean d'arme    schedule 13.06.2015    source источник
comment
@cYrixmorten, может быть, ты - я знаю, что ты действительно хорошо разбираешься в этих   -  person jean d'arme    schedule 13.06.2015
comment
Не думаю, что я столкнулся именно с этой проблемой, но я все же могу подумать, что у меня есть предложение. Сделал бы ответ через мгновение.   -  person cYrixmorten    schedule 14.06.2015
comment
Только что заметил, что вы используете только первый результат followList2: followList2.get(0). В качестве оптимизации вы можете сделать query3.getFirstInBackground(...) вместо query3.findInBackground(...)   -  person cYrixmorten    schedule 14.06.2015
comment
Да, действительно getFirstInBackground лучший выбор. Странно, я видел это раньше в quide и все же не использовал его!   -  person jean d'arme    schedule 14.06.2015


Ответы (1)


Если я правильно вас понял, вы уже пробовали:

...
public void done(final List<ParseObject> followList2, ParseException e) {
...

Что по какой-то причине делает компилятор недовольным.

Я думаю, что может быть два возможных решения

  1. Если вы планируете использовать объекты followList2 в другом месте вашего Activity/Fragment. Затем просто объявите переменную поля для хранения результата и чтения вместо этого. Таким образом, анонимный внутренний класс должен иметь к нему доступ.
  2. Запишите 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, Bolts практически не отличается от Java. Это устраняет необходимость вложенных вызовов, создавая фрагмент кода в форме пирамиды по мере роста количества зависимых запросов. Однако на привыкание требуется некоторое время, а в простых случаях оно и не нужно.

Бонус:

Поскольку у вас возникли проблемы с использованием текста из вашего включения в адаптер, я покажу вам часть своего кода в качестве примера.

Во-первых, у меня есть простой макет для элемента: 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") (включает весь указатель «local») или `query.include («local.place») (включает только столбец «место» в «local»);

Дополнительный бонус — создание подклассов

И последнее замечание: похоже, вы не используете подклассы, но если бы вы это делали, у вас также мог бы быть специализированный пользовательский адаптер для подклассов Cena.

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");
}
person cYrixmorten    schedule 13.06.2015
comment
Рад слышать, что это работает :-) точечная нотация, такая как lokal.place, работает только для включения в запросы. Поэтому, когда вы делаете setText(local.place), адаптер пытается использовать столбец с именем lokal.place в Cena, он не будет прыгать с указателем. Я думаю, вам придется создать свой собственный адаптер, расширяющий ParseQueryAdapter, а затем вручную установить текстовое представление с помощью cena.getParseObject(local).getString(place) - person cYrixmorten; 14.06.2015
comment
Так что, по сути, нет смысла использовать query.include(), потому что нет возможности использовать его с помощью базового ParseQueryAdaper. Я начал с public class ParseQueryCustomAdapter extends ParseQueryAdapter<T extends ParseObject> и уже получил ошибку Unexpected bound. Я делаю что-то не так? - person jean d'arme; 14.06.2015
comment
Добавлено несколько дополнительных примеров кода. В основном не проверено, так что может быть опечатка или две, но надеюсь, вы поняли картину :) - person cYrixmorten; 14.06.2015
comment
Работает как шарм! Я добавляю к адаптеру третий аргумент, чтобы я мог получить cena из базового объекта :) Я думаю, вы работаете на Parse.com или слишком глубоко разбираетесь в их вещах. Я очень благодарен за Вашу помощь и время - это довольно исчерпывающий ответ (особенно бонусы!) - person jean d'arme; 15.06.2015
comment
Хе-хе, я только что потратил много времени на разработку приложения Parse :-) рад, что оно работает, и удачного кодирования ;-) - person cYrixmorten; 15.06.2015