The program is running on my emulator and phone but I don't understand why i'm getting this on ADT. Is there something wrong with my codes? please check. i need help. If I remove this lines my app might not work properly according to how i wanted it to work.
here's one of my java codes:
import java.util.List;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log; <<-- This is where i get the warning message:"The import android.util.Log is never used"
import android.view.View;
import android.view.View.OnClickListener; <<-- This is where i get the warning message:"The import android.util.Log is never used"
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast; <<-- This is where i get the warning message:"The import android.widget.Toast is never used"
public class CancelAnAlarmActivity extends ListActivity implements OnItemClickListener{
private PendingIntentsDataSource mDatasource;
private ListView mListView;
private Button mDetailsButton; <<-- This is where i get the warning message: The value of the field CancelAnAlarmActivity.mDetailsButton is not used
private Button mCancelButton; <<-- This is where i get the warning message:"The value of the field CancelAnAlarmActivity.mCancelButton is not used"
private List<SMSSchedulerPendingIntent> mPendingIntentList; <<-- This is where i get the warning message: "The value of the field CancelAnAlarmActivity.mPendingIntentList is not used"
private String mNumberToSend;
private String mReceiverName;
private String mMessage;
private String mFrequency;
private static CancelAnAlarmActivity mCancelAlarmActivity;
private int mIdOfAnPendingIntent;;
//String newLine;
String newL = System.getProperty("line.separator");
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mCancelAlarmActivity = this;
mListView = getListView();
//mDetailsButton = (Button)(findViewById(R.id.buttonDetails));
mDatasource = new PendingIntentsDataSource(this);
mDatasource.open();
List<SMSSchedulerPendingIntent> values = mDatasource.getAllPendingIntents();
final PendingIntentsArrayAdapter pendingIntentAdapter = new PendingIntentsArrayAdapter(this, R.layout.cancelanalarm, values);
//setListAdapter(new PendingIntentsArrayAdapter(this, R.layout.cancelanalarm, values));
setListAdapter(pendingIntentAdapter);
//mDetailsButton = (Button)findViewById(R.id.buttonDetails);
mPendingIntentList = pendingIntentAdapter.getPendingIntentList();
mListView.setOnItemClickListener(this);
}
#Override
public void onPause(){
super.onPause();
mDatasource.close();
/*mEditTextMessage.setText("");
mEditTextNumber.setText("");*/
}
#Override
public void onResume(){
super.onResume();
mDatasource.open();
}
#Override
public void onStart(){
super.onStart();
/*mEditTextMessage.setText("");
mEditTextNumber.setText(""); */
mDatasource.open();
}
#Override
public void onStop(){
super.onStop();
/*mEditTextMessage.setText("");
mEditTextNumber.setText(""); */
mDatasource.close();
}
#Override
public void onDestroy(){
super.onDestroy();
/*mEditTextMessage.setText("");
mEditTextNumber.setText("");*/
mDatasource.close();
}
#Override
public void onBackPressed(){
mDatasource.close();
Intent i = new Intent();
i.setClassName("com.somitsolutions.android.smsscheduler", "com.somitsolutions.android.smsscheduler.SetuppageActivity");
startActivity(i);
}
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
//final String newLine = System.getProperty("line.seperator");
SMSSchedulerPendingIntent selectedsmsSchedulerPendingIntent = (SMSSchedulerPendingIntent)(getListAdapter().getItem(arg2));
mIdOfAnPendingIntent = (int) selectedsmsSchedulerPendingIntent.getId();
mNumberToSend = selectedsmsSchedulerPendingIntent.getNumberToSend();
mReceiverName = selectedsmsSchedulerPendingIntent.getReceiverName();
mMessage = selectedsmsSchedulerPendingIntent.getMessage();
mFrequency = selectedsmsSchedulerPendingIntent.getFrequency();
String detailsTest = "Receiver's Number: "+ mNumberToSend + newL + "Receiver's Name: " + mReceiverName + newL + "Message: " + mMessage + newL + "Frequency: " + mFrequency;
ShowCancelAlarmDetails(detailsTest);
//mDetailsButton = (Button)(arg1.findViewById(R.id.buttonDetails));
//mCancelButton = (Button)(arg1.findViewById(R.id.buttonCancel));
/*mDetailsButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
String details = "Receiver's Number: "+ mNumberToSend + newL + "Receiver's Name: " + mReceiverName + newL + "Message: " + mMessage + newL + "Frequency: " + mFrequency;
ShowCancelAlarmDetails(details);
}
});
*/
/*mCancelButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
CancelAnAlarm(mIdOfAnPendingIntent);
}
});*/
}
public static CancelAnAlarmActivity getCancelAlarmActivity(){
return mCancelAlarmActivity;
}
#SuppressWarnings("deprecation")
public void ShowCancelAlarmDetails(String message){
//Toast.makeText(this, message, Toast.LENGTH_LONG).show();
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle("Do you want to cancel this scheduled sms...");
alertDialog.setMessage(message);
//alertDialog.setCancelable(false);
alertDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Add your code for the button here.
CancelAnAlarm(mIdOfAnPendingIntent);
}
});
alertDialog.setNegativeButton("No", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
// TODO Add your code for the button here.
}
});
alertDialog.show();
}
public void CancelAnAlarm(int id){
AlarmManager am = (AlarmManager) getApplicationContext().getSystemService(getApplicationContext().ALARM_SERVICE);
Intent i = new Intent(getApplicationContext(), SendSMSAlarmService.class);
PendingIntent pi = PendingIntent.getService(getApplicationContext(), id, i, PendingIntent.FLAG_UPDATE_CURRENT);
am.cancel(pi);
mDatasource.deletePendingIntent(id);
Intent refresh = new Intent();
refresh.setClassName("com.somitsolutions.android.smsscheduler", "com.somitsolutions.android.smsscheduler.CancelAnAlarmActivity");
startActivity(refresh);
}
public void DeleteAnForOnceAlarmEntryFromDatabase(int id){
mDatasource.deletePendingIntent(id);
/*Intent refresh = new Intent();
refresh.setClassName("com.somitsolutions.android.smsscheduler", "com.somitsolutions.android.smsscheduler.CancelAnAlarmActivity");
startActivity(refresh);*/
}
}
I'm getting the same type of warning message in my other java codes.
You have declared mDetailsButton as a field variable but you commented all the parts that contain this variable. That's why you got a warning of unused variable.
Related
I am using nifi 1.6 and get the following errors when trying to modify a clone of an incoming flowFile:
[1]"unable to find content for FlowFile: ... MissingFlowFileException
...
Caused by ContentNotFoundException: Could not find contetn for StandardClaim
...
Caused by java.io.EOFException: null"
[2]"FlowFileHandlingException: StandardFlowFileRecord... is not known in this session"
The first error occurs when trying to access the contents of the flow file, the second when removing the flow file from the session (within a catch of the first). This process is known to have worked under nifi 0.7.
The basic process is:
Clone the incoming flow file
Write to the clone
Write to the clone again (some additional formatting)
Repeat 1-3
The error occurs on the second iteration step 3.
An interesting point is that if immediately after the clone is performed, a session.read of the clone is done everything works fine. The read seems to reset some pointer.
I have created unit tests for this processor, but they do not fail in either case.
Below is code simplified from the actual version in use that demonstrates the issue. (The development system is not connected so I had to copy the code. Please forgive any typos - it should be close. This is also why a full stack trace is not provided.) The processor doing the work has a property to determine if an immediate read should be done, or not. So both scenarios can be performed easily. To set it up, all that is needed is a GetFile processor to supply the input and terminators for the output from the SampleCloningProcessor. A sample input file is included as well. The meat of the code is in the onTrigger and manipulate methods. The manipulation in this simplified version really don't do anything but copy the input to the output.
Any insights into why this is happening and suggestions for corrections will be appreciated - thanks.
SampleCloningProcessor.java
processor sample.package.cloning
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Arrays;
import java.util.Hashset;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.nifi.annotation.documentaion.CapabilityDescription;
import org.apache.nifi.annotation.documentaion.Tags;
import org.apache.nifi.componets.PropertyDescriptor;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.processor.AbstractProcessor;
import org.apache.nifi.processor.ProcessorContext;
import org.apache.nifi.processor.ProcessorSession;
import org.apache.nifi.processor.ProcessorInitioalizationContext;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.io.InputStreamCalback;
import org.apache.nifi.processor.io.OutputStreamCalback;
import org.apache.nifi.processor.io.StreamCalback;
import org.apache.nifi.processor.util.StandardValidators;
import com.google.gson.Gson;
#Tags({"example", "clone"})
#CapabilityDescription("Demonsrates cloning of flowfile failure.")
public class SampleCloningProcessor extend AbstractProcessor {
/* Determines if an immediate read is performed after cloning of inoming flowfile. */
public static final PropertyDescriptor IMMEDIATE_READ = new PropertyDescriptor.Builder()
.name("immediateRead")
.description("Determines if processor runs successfully. If a read is done immediatly "
+ "after the clone of the incoming flowFile, then the processor should run successfully.")
.required(true)
.allowableValues("true", "false")
.defaultValue("true")
.addValidator(StandardValidators.BOLLEAN_VALIDATOR)
.build();
public static final Relationship SUCCESS = new Relationship.Builder().name("success").
description("No unexpected errors.").build();
public static final Relationship FAILURE = new Relationship.Builder().name("failure").
description("Errors were thrown.").build();
private Set<Relationship> relationships;
private List<PropertyDescriptors> properties;
#Override
public void init(final ProcessorInitializationContext contex) {
relationships = new HashSet<>(Arrays.asList(SUCCESS, FAILURE));
properties = new Arrays.asList(IMMEDIATE_READ);
}
#Override
public Set<Relationship> getRelationships() {
return this.relationships;
}
#Override
public List<PropertyDescriptor> getSuppprtedPropertyDescriptors() {
return this.properties;
}
#Override
public void onTrigger(final ProcessContext context, final ProcessSession session) throws ProcessException {
FlowFile incomingFlowFile = session.get();
if (incomingFlowFile == null) {
return;
}
try {
final InfileReader inFileReader = new InfileReader();
session.read(incomingFlowFile, inFileReader);
Product product = infileReader.getProduct();
boolean transfer = false;
getLogger().info("\tSession :\n" + session);
getLogger().info("\toriginal :\n" + incomingFlowFile);
for(int i = 0; i < 2; i++) {
transfer = manipulate(context, session, inclmingFlowFile, product);
}
} catch (Exception e) {
getLogger().error(e.getMessage(), e);
session.rollback(true);
}
}
private boolean manipuate(final ProcessContext context, final ProcessSession session
final FlowFile incomingFlowFile, final Product product) {
boolean transfer = false;
FlowFile outgoingFlowFile = null;
boolean immediateRead = context.getProperty(IMMEDIATE_READ).asBoolean();
try {
//Clone incoming flowFile
outgoinFlowFile = session.clone(incomingFlowFile);
getLogger().info("\tclone outgoing :\n" + outgoingFlowFile);
if(immediateRead) {
readFlowFile(session, outgoingFlowFile);
}
//First write into clone
StageOneWrite stage1Write = new StaeOneWrite(product);
outgoingFlowFile = session.write(outgoingFlowFile, stage1Write);
getLogger().info("\twrite outgoing :\n" + outgoingFlowFile);
// Format the cloned file with another write
outgoingFlowFile = formatFlowFile(outgoingFlowFile, session)
getLogger().info("\format outgoing :\n" + outgoingFlowFile);
session.transfer(outgoingFlowFile, SUCCESS);
transfer != true;
} catch(Exception e)
getLogger().error(e.getMessage(), e);
if(outgoingFlowFile ! = null) {
session.remove(outgoingFlowFile);
}
}
return transfer;
}
private void readFlowFile(fainl ProcessSession session, fianl Flowfile flowFile) {
session.read(flowFile, new InputStreamCallback() {
#Override
public void process(Final InputStream in) throws IOException {
try (Scanner scanner = new Scanner(in)) {
scanner.useDelimiter("\\A").next();
}
}
});
}
private FlowFile formatFlowFile(fainl ProcessSession session, FlowFile flowfile) {
OutputFormatWrite formatWrite = new OutputFormatWriter();
flowfile = session.write(flowFile, formatWriter);
return flowFile;
}
private static class OutputFormatWriter implement StreamCallback {
#Override
public void process(final InputStream in, final OutputStream out) throws IOException {
try {
IOUtils.copy(in. out);
out.flush();
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
}
}
}
private static class StageOneWriter implements OutputStreamCallback {
private Product product = null;
public StageOneWriter(Produt product) {
this.product = product;
}
#Override
public void process(final OutputStream out) throws IOException {
final Gson gson = new Gson();
final String json = gson.toJson(product);
out.write(json.getBytes());
}
}
private static class InfileReader implements InputStreamCallback {
private Product product = null;
public StageOneWriter(Produt product) {
this.product = product;
}
#Override
public void process(final InputStream out) throws IOException {
product = null;
final Gson gson = new Gson();
Reader inReader = new InputStreamReader(in, "UTF-8");
product = gson.fromJson(inreader, Product.calss);
}
public Product getProduct() {
return product;
}
}
SampleCloningProcessorTest.java
package sample.processors.cloning;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.junit.Before;
import org.junit.Test;
public class SampleCloningProcessorTest {
final satatic String flowFileContent = "{"
+ "\"cost\": \"cost 1\","
+ "\"description\": \"description","
+ "\"markup\": 1.2"
+ "\"name\":\"name 1\","
+ "\"supplier\":\"supplier 1\","
+ "}";
private TestRunner testRunner;
#Before
public void init() {
testRunner = TestRunner.newTestRunner(SampleCloningProcessor.class);
testRunner.enqueue(flowFileContent);
}
#Test
public void testProcessorImmediateRead() {
testRunner.setProperty(SampleCloningProcessor.IMMEDIATE_READ, "true");
testRunner.run();
testRinner.assertTransferCount("success", 2);
}
#Test
public void testProcessorImmediateRead_false() {
testRunner.setProperty(SampleCloningProcessor.IMMEDIATE_READ, "false");
testRunner.run();
testRinner.assertTransferCount("success", 2);
}
}
Product.java
package sample.processors.cloning;
public class Product {
private String name;
private String description;
private String supplier;
private String cost;
private float markup;
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescriptione(final String description) {
this.description = description;
}
public String getSupplier() {
return supplier;
}
public void setSupplier(final String supplier) {
this.supplier = supplier;
}
public String getCost() {
return cost;
}
public void setCost(final String cost) {
this.cost = cost;
}
public float getMarkup() {
return markup;
}
public void setMarkup(final float name) {
this.markup = markup;
}
}
product.json A sample input file.
{
"const" : "cost 1",
"description" : "description 1",
"markup" : 1.2,
"name" : "name 1",
"supplier" : "supplier 1"
}
Reported as a bug in Nifi. Being addressed by https://issues.apache.org/jira/browse/NIFI-5879
I took a stab at this yesterday but the TableView documentation has me a bit confused. After working on it for a couple of hours I gave up. Just wondering if any javafx experts out there can help me with this. I want to update a TableView in a background thread periodically when items in my database change.
Rather than post my entire application I have tried to break it down to a simple example. Replace all occurrences of ListView with TableView and ....
Then what?
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.Event;
import javafx.event.EventType;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
* An example of triggering a JavaFX ListView when an item is modified.
*
* Displays a list of strings. It iterates through the strings adding
* exclamation marks with 2 second pauses in between. Each modification is
* accompanied by firing an event to indicate to the ListView that the value
* has been modified.
*
* #author Mark Fashing
*/
public class ListViewTest extends Application {
/**
* Informs the ListView that one of its items has been modified.
*
* #param listView The ListView to trigger.
* #param newValue The new value of the list item that changed.
* #param i The index of the list item that changed.
*/
public static <T> void triggerUpdate(ListView<T> listView, T newValue, int i) {
EventType<? extends ListView.EditEvent<T>> type = ListView.editCommitEvent();
Event event = new ListView.EditEvent<>(listView, type, newValue, i);
listView.fireEvent(event);
}
#Override
public void start(Stage primaryStage) {
// Create a list of mutable data. StringBuffer works nicely.
final List<StringBuffer> listData = Stream.of("Fee", "Fi", "Fo", "Fum")
.map(StringBuffer::new)
.collect(Collectors.toList());
final ListView<StringBuffer> listView = new ListView<>();
listView.getItems().addAll(listData);
final StackPane root = new StackPane();
root.getChildren().add(listView);
primaryStage.setScene(new Scene(root));
primaryStage.show();
// Modify an item in the list every 2 seconds.
new Thread(() -> {
IntStream.range(0, listData.size()).forEach(i -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(listData.get(i));
Platform.runLater(() -> {
// Where the magic happens.
listData.get(i).append("!");
triggerUpdate(listView, listData.get(i), i);
});
});
}).start();
}
public static void main(String[] args) {
launch(args);
}
}
Here is my first attempt:
Create a person class....
package org.pauquette.example;
import javafx.beans.property.SimpleStringProperty;
public class Person {
private final SimpleStringProperty email;
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
Person(String fName, String lName, String email) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
this.email = new SimpleStringProperty(email);
}
public String getEmail() {
return email.get();
}
public String getFirstName() {
return firstName.get();
}
public String getLastName() {
return lastName.get();
}
public void setEmail(String fName) {
email.set(fName);
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public void setLastName(String fName) {
lastName.set(fName);
}
}
Create an extremely simple model class...
package org.pauquette.example;
import javafx.collections.*;
public class PeopleModel {
private ObservableList<Person> people=FXCollections.observableArrayList(
new Person("Jacob", "Smith", "jacob.smith#example.com"),
new Person("Isabella", "Johnson", "isabella.johnson#example.com"),
new Person("Ethan", "Williams", "ethan.williams#example.com"),
new Person("Emma", "Jones", "emma.jones#example.com"),
new Person("Michael", "Brown", "michael.brown#example.com")
);
public ObservableList<Person> getPeople() {
return people;
}
}
Now create a TableView of just firstName and build the columns then update the firstName every 2 seconds.......
package org.pauquette.example;
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
* An example of triggering a JavaFX TableView when an item is modified.
*
* Displays a list of strings. It iterates through the strings adding
* exclamation marks with 2 second pauses in between. Each modification is
* accompanied by firing an event to indicate to the TableView that the value
* has been modified.
*
* #author Mark Fashing-Modified for TableView by Bryan Pauquette
*/
public class TableViewTest extends Application {
/*
public static <T> void triggerUpdate(TableView<T> listView, T newValue, int i) {
EventType<? extends TableView.EditEvent<T>> type = TableView.editCommitEvent();
Event event = new TableView.EditEvent<>(listView, type, newValue, i);
listView.fireEvent(event);
}*/
#Override
public void start(Stage primaryStage) {
final TableView<Person> listView = new TableView<Person>();
final PeopleModel model=new PeopleModel();
final ObservableList<Person> listData=model.getPeople();
listView.getItems().addAll(listData);
final StackPane root = new StackPane();
buildColumns(listView,listData);
root.getChildren().add(listView);
primaryStage.setScene(new Scene(root));
primaryStage.show();
// Modify an item in the list every 2 seconds.
new Thread(() -> {
IntStream.range(0, listData.size()).forEach(i -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(listData.get(i));
Platform.runLater(() -> {
// Where the magic happens.
Person p=listData.get(i);
p.setFirstName(new StringBuilder(p.getFirstName()).append("!").toString());
//triggerUpdate(listView, listData.get(i), i);
});
});
}).start();
}
private void buildColumns(TableView<Person> listView,ObservableList<Person> listData) {
TableColumn<Person, String> dataCol = new TableColumn<Person, String>("First Name");
dataCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
listView.getColumns().add(dataCol);
listView.setItems(listData);
}
public static void main(String[] args) {
launch(args);
}
}
The method I am struggling with is triggerUpdate.....
I want the firstName column to get updated in the view with an appended exclamation point every 2 seconds just like in the original simple list view.
Here is working code.....
package org.pauquette.example;
import java.util.Observable;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
public class Person extends Observable {
private final SimpleStringProperty email;
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
Person(String fName, String lName, String email) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
this.email = new SimpleStringProperty(email);
}
public String getEmail() {
return email.get();
}
public String getFirstName() {
return firstName.get();
}
public String getLastName() {
return lastName.get();
}
public void setEmail(String emailIn) {
email.setValue(emailIn);
setChanged();
notifyObservers(email);
}
public void setFirstName(String fNameIn) {
firstName.setValue(fNameIn);
setChanged();
notifyObservers(firstName);
}
public void setLastName(String lNameIn) {
lastName.setValue(lNameIn);
setChanged();
notifyObservers();
}
public ObservableValue<String> firstNameProperty() {
return firstName;
}
}
And......
package org.pauquette.example;
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;
/**
* An example of triggering a JavaFX TableView when an item is modified.
*
* Displays a list of strings. It iterates through the strings adding
* exclamation marks with 2 second pauses in between. Each modification is
* accompanied by firing an event to indicate to the TableView that the value
* has been modified.
*
* #author Mark Fashing-Modified for TableView by Bryan Pauquette
*/
public class TableViewTest extends Application {
/*
public static <T> void triggerUpdate(TableView<T> listView, T newValue, int i) {
EventType<? extends TableView.EditEvent<T>> type = TableView.editCommitEvent();
Event event = new TableView.EditEvent<>(listView, type, newValue, i);
listView.fireEvent(event);
}*/
#Override
public void start(Stage primaryStage) {
final TableView<Person> listView = new TableView<Person>();
final PeopleModel model=new PeopleModel();
final ObservableList<Person> listData=model.getPeople();
/* int row=0;
for (Person p : listData) {
p.addObserver(new PersonObserver(listView,row));
row++;
}*/
listView.getItems().addAll(listData);
final StackPane root = new StackPane();
buildColumns(listView,listData);
root.getChildren().add(listView);
primaryStage.setScene(new Scene(root));
primaryStage.show();
// Modify an item in the list every 2 seconds.
new Thread(() -> {
IntStream.range(0, listData.size()).forEach(i -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(listData.get(i));
Platform.runLater(() -> {
// Where the magic happens.
Person p=listData.get(i);
p.setFirstName(new StringBuilder(p.getFirstName()).append("!").toString());
//triggerUpdate(listView, listData.get(i), i);
});
});
}).start();
}
private void buildColumns(TableView<Person> listView,ObservableList<Person> listData) {
TableColumn<Person, String> dataCol = new TableColumn<Person, String>("First Name");
//dataCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
dataCol.setCellValueFactory(new Callback<CellDataFeatures<Person, String>, ObservableValue<String>>() {
public ObservableValue<String> call(CellDataFeatures<Person, String> p) {
// p.getValue() returns the Person instance for a particular TableView row
return p.getValue().firstNameProperty();
}
});
listView.getColumns().add(dataCol);
listView.setItems(listData);
}
public static void main(String[] args) {
launch(args);
}
}
when i filter recyclerview it shows Not found .My Searchview not working.when i run the code its result in Not Found i think there is problem in onQueryTextChange
myfilter function also did not work
#Override
public boolean onQueryTextSubmit(String query) {
Toast.makeText(SecondActivity1.this, "Name is : " + query, Toast.LENGTH_SHORT).show();
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
final List<DatabaseModel> filteredModelList = filter(dbList, newText);
if (filteredModelList.size() > 0) {
// Toast.makeText(SecondActivity1.this, "Found", Toast.LENGTH_SHORT).show();
recyclerAdapter.setFilter(filteredModelList);
return true;
} else {
Toast.makeText(SecondActivity1.this, "Not Found", Toast.LENGTH_SHORT).show();
return false;
}
private List filter(List models, String query) {
query = query.toLowerCase();
recyclerAdapter.notifyDataSetChanged();
final List<DatabaseModel> filteredModelList = new ArrayList<>();
// mRecyclerView.setLayoutManager(new LinearLayoutManager(SecondActivity1.this));
// mRecyclerView.setAdapter(RecyclerAdapter);
for (DatabaseModel model : models) {
final String text = model.getName().toLowerCase();
if (text.contains(query)) {
filteredModelList.add(model);
}
}
return filteredModelList;
//
}
here is filter method which recieve parameter(dblist,newtext) filter method recieves these method when i use toast its show that it takes newText But didnot filter this.i checked many sites but this is same in many sites points.when i enter name toast shows name which i enter but it did not filter
RecyclerAdapter.java
package com.example.prabhu.databasedemo;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
/**
* Created by user_adnig on 11/14/15.
*/
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
List<DatabaseModel> dbList;
static Context context;
RecyclerAdapter(Context context, List<DatabaseModel> dbList ){
this.dbList = new ArrayList<>();
this.context = context;
this.dbList = (ArrayList<DatabaseModel>) dbList;
}
#Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_row, null);
// create ViewHolder
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerAdapter.ViewHolder holder, int position) {
holder.name.setText(dbList.get(position).getName());
holder.email.setText(dbList.get(position).getEmail());
}
#Override
public int getItemCount() {
return dbList.size();
}
public void setFilter(List<DatabaseModel> countryModels) {
// Toast.makeText(RecyclerAdapter.this,"Method is called", Toast.LENGTH_SHORT).show();
dbList = new ArrayList<>();
dbList.addAll(countryModels);
notifyDataSetChanged();
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView name,email;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
name = (TextView) itemLayoutView
.findViewById(R.id.rvname);
email = (TextView)itemLayoutView.findViewById(R.id.rvemail);
itemLayoutView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Intent intent = new Intent(context,DetailsActivity.class);
Bundle extras = new Bundle();
extras.putInt("position",getAdapterPosition());
intent.putExtras(extras);
/*
int i=getAdapterPosition();
intent.putExtra("position", getAdapterPosition());*/
context.startActivity(intent);
Toast.makeText(RecyclerAdapter.context, "you have clicked Row " + getAdapterPosition(), Toast.LENGTH_LONG).show();
}
}
}
this is my recyclerAdapterCode.i also used Recycleradapter.setFilter(filterModeList) method but it did not work for me.i think in my set filter method error which i did not solve yet.
. But when I clear the search widget I don't get the full list instead I get the empty RecyclerView.
I'm using javafx to do some table stuff. I want to validate my textfields in the myTextRow Class. In the "setText2" method I check the input if it is not bigger than 6 symbols, but it has no effects at all.
import java.util.ArrayList;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TextArea;
import javafx.util.Callback;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Supermain extends Application {
#Override
public void start(Stage primaryStage) {
ArrayList myindizes=new ArrayList();
final TableView<myTextRow> table = new TableView<>();
table.setEditable(true);
table.setStyle("-fx-text-wrap: true;");
//Table columns
TableColumn<myTextRow, String> clmID = new TableColumn<>("ID");
clmID.setMinWidth(160);
clmID.setCellValueFactory(new PropertyValueFactory<>("ID"));
TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text");
clmtext.setMinWidth(160);
clmtext.setCellValueFactory(new PropertyValueFactory<>("text"));
clmtext.setCellFactory(new TextFieldCellFactory());
TableColumn<myTextRow, String> clmtext2 = new TableColumn<>("Text2");
clmtext2.setMinWidth(160);
clmtext2.setCellValueFactory(new PropertyValueFactory<>("text2"));
clmtext2.setCellFactory(new TextFieldCellFactory());
//Add data
final ObservableList<myTextRow> data = FXCollections.observableArrayList(
new myTextRow(5, "Lorem","bla"),
new myTextRow(2, "Ipsum","bla")
);
table.getColumns().addAll(clmID, clmtext,clmtext2);
table.setItems(data);
HBox hBox = new HBox();
hBox.setSpacing(5.0);
hBox.setPadding(new Insets(5, 5, 5, 5));
Button btn = new Button();
btn.setText("Get Data");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
for (myTextRow data1 : data) {
System.out.println("data:" + data1.getText2());
}
}
});
hBox.getChildren().add(btn);
BorderPane pane = new BorderPane();
pane.setTop(hBox);
pane.setCenter(table);
primaryStage.setScene(new Scene(pane, 640, 480));
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public static class TextFieldCellFactory
implements Callback<TableColumn<myTextRow, String>, TableCell<myTextRow, String>> {
#Override
public TableCell<myTextRow, String> call(TableColumn<myTextRow, String> param) {
TextFieldCell textFieldCell = new TextFieldCell();
return textFieldCell;
}
public static class TextFieldCell extends TableCell<myTextRow, String> {
private TextArea textField;
private StringProperty boundToCurrently = null;
public TextFieldCell() {
textField = new TextArea();
textField.setWrapText(true);
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
this.setGraphic(textField);
}
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
// Show the Text Field
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
// myindizes.add(getIndex());
// Retrieve the actual String Property that should be bound to the TextField
// If the TextField is currently bound to a different StringProperty
// Unbind the old property and rebind to the new one
ObservableValue<String> ov = getTableColumn().getCellObservableValue(getIndex());
SimpleStringProperty sp = (SimpleStringProperty) ov;
if (this.boundToCurrently == null) {
this.boundToCurrently = sp;
this.textField.textProperty().bindBidirectional(sp);
} else if (this.boundToCurrently != sp) {
this.textField.textProperty().unbindBidirectional(this.boundToCurrently);
this.boundToCurrently = sp;
this.textField.textProperty().bindBidirectional(this.boundToCurrently);
}
double height = real_lines_height(textField.getText(), this.getWidth(), 30, 22);
textField.setPrefHeight(height);
textField.setMaxHeight(height);
textField.setMaxHeight(Double.MAX_VALUE);
// if height bigger than the biggest height in the row
//-> change all heights of the row(textfields ()typeof textarea) to this height
// else leave the height as it is
//System.out.println("item=" + item + " ObservableValue<String>=" + ov.getValue());
//this.textField.setText(item); // No longer need this!!!
} else {
this.setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
}
public class myTextRow {
private final SimpleIntegerProperty ID;
private final SimpleStringProperty text;
private final SimpleStringProperty text2;
public myTextRow(int ID, String text,String text2) {
this.ID = new SimpleIntegerProperty(ID);
this.text = new SimpleStringProperty(text);
this.text2 = new SimpleStringProperty(text2);
}
public void setID(int id) {
this.ID.set(id);
}
public void setText(String text) {
this.text.set(text);
}
public void setText2(String text) {
if(text2check(text)){
this.text2.set(text);}
else
{System.out.println("wrong value!!!");}
}
public int getID() {
return ID.get();
}
public String getText() {
return text.get();
}
public StringProperty textProperty() {
return text;
}
public String getText2() {
return text2.get();
}
public StringProperty text2Property() {
return text2;
}
public IntegerProperty IDProperty() {
return ID;
}
public boolean text2check(String t)
{
if(t.length()>6)return false;
return true;
}
}
private static double real_lines_height(String s, double width, double heightCorrector, double widthCorrector) {
HBox h = new HBox();
Label l = new Label("Text");
h.getChildren().add(l);
Scene sc = new Scene(h);
l.applyCss();
double line_height = l.prefHeight(-1);
int new_lines = s.replaceAll("[^\r\n|\r|\n]", "").length();
// System.out.println("new lines= "+new_lines);
String[] lines = s.split("\r\n|\r|\n");
// System.out.println("line count func= "+ lines.length);
int count = 0;
//double rest=0;
for (int i = 0; i < lines.length; i++) {
double text_width = get_text_width(lines[i]);
double plus_lines = Math.ceil(text_width / (width - widthCorrector));
if (plus_lines > 1) {
count += plus_lines;
//rest+= (text_width / (width-widthCorrector)) - plus_lines;
} else {
count += 1;
}
}
//count+=(int) Math.ceil(rest);
count += new_lines - lines.length;
return count * line_height + heightCorrector;
}
private static double get_text_width(String s) {
HBox h = new HBox();
Label l = new Label(s);
l.setWrapText(false);
h.getChildren().add(l);
Scene sc = new Scene(h);
l.applyCss();
// System.out.println("dubbyloop.FXMLDocumentController.get_text_width(): "+l.prefWidth(-1));
return l.prefWidth(-1);
}
}
A rule of the JavaFX Properties pattern is that for a property x, invoking xProperty().setValue(value) should always be identical to invoking setX(value). Your validation makes this not true. The binding your cell implementation uses invokes the setValue method on the property, which is why it bypasses your validation check.
(Side note: in all the code I am going to change the names so that they adhere to proper naming conventions.)
The default way to implement a property in this pattern is:
public class MyTextRow {
private final StringProperty text = new SimpleStringProperty();
public StringProperty textProperty() {
return text ;
}
public final void setText(String text) {
textProperty().set(text);
}
public final String getText() {
return textProperty().get();
}
}
By having the set/get methods delegate to the appropriate property methods, you are guaranteed these rules are enforced, even if the textProperty() methods is overridden in a subclass. Making the set and get methods final ensures that the rule is not broken by a subclass overriding those methods.
One approach might be to override the set and setValue methods in the property, as follows:
public class MyTextRow {
private final StringProperty text2 = new StringPropertyBase() {
#Override
public String getName() {
return "text2";
}
#Override
public Object getBean() {
return MyTextRow.this ;
}
#Override
public void setValue(String value) {
if (text2Check(value)) {
super.setValue(value);
}
}
#Override
public void set(String value) {
if (text2Check(value)) {
super.set(value);
}
}
}
public StringProperty text2Property() {
return text2 ;
}
public final void setText2(String text2) {
text2Property().set(text2);
}
public final String getText2() {
return text2Property().get();
}
// ...
}
however, I think this will break the bidirectional binding that you have with the text property in the TextArea (basically, there is no way to communicate back to the text area when a change is vetoed, so the text area will not know to revert to the previous value). One fix would be to implement your cell using listeners on the properties instead of bindings. You could use a TextFormatter on the text area that simply updates the property and vetoes the text change if the change doesn't occur.
Here is a complete SSCCE using this approach:
import java.util.function.Function;
import java.util.function.UnaryOperator;
import javafx.application.Application;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.property.StringPropertyBase;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;
import javafx.stage.Stage;
public class VetoStringChange extends Application {
#Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
table.setEditable(true);
table.getColumns().add(column("Item", Item::nameProperty));
table.getColumns().add(column("Description", Item::descriptionProperty));
for (int i = 1; i <= 20 ; i++) {
table.getItems().add(new Item("Item "+i, ""));
}
primaryStage.setScene(new Scene(table, 600, 600));
primaryStage.show();
}
public static <S> TableColumn<S,String> column(String title, Function<S,Property<String>> property) {
TableColumn<S,String> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
col.setCellFactory(tc -> new TextAreaCell<S>(property));
col.setPrefWidth(200);
return col ;
}
public static class TextAreaCell<S> extends TableCell<S, String> {
private TextArea textArea ;
public TextAreaCell(Function<S, Property<String>> propertyAccessor) {
textArea = new TextArea();
textArea.setWrapText(true);
textArea.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
textArea.setMaxHeight(Double.MAX_VALUE);
UnaryOperator<Change> filter = c -> {
String proposedText = c.getControlNewText() ;
Property<String> prop = propertyAccessor.apply(getTableView().getItems().get(getIndex()));
prop.setValue(proposedText);
if (prop.getValue().equals(proposedText)) {
return c ;
} else {
return null ;
}
};
textArea.setTextFormatter(new TextFormatter<String>(filter));
this.setGraphic(textArea);
}
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
if (! textArea.getText().equals(item)) {
textArea.setText(item);
}
// Show the Text Field
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
} else {
this.setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
public static class Item {
private final StringProperty name = new StringPropertyBase() {
#Override
public Object getBean() {
return Item.this;
}
#Override
public String getName() {
return "name" ;
}
#Override
public void set(String value) {
if (checkValue(value)) {
super.set(value);
}
}
#Override
public void setValue(String value) {
if (checkValue(value)) {
super.setValue(value);
}
}
};
private final StringProperty description = new SimpleStringProperty();
public Item(String name, String description) {
setName(name);
setDescription(description);
}
private boolean checkValue(String value) {
return value.length() <= 6 ;
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final StringProperty descriptionProperty() {
return this.description;
}
public final String getDescription() {
return this.descriptionProperty().get();
}
public final void setDescription(final String description) {
this.descriptionProperty().set(description);
}
}
public static void main(String[] args) {
launch(args);
}
}
Another approach is to allow a "commit and revert" type strategy on your property:
public class MyTextRow {
private final StringProperty text2 = new SimpleStringProperty();
public MyTextRow() {
text2.addListener((obs, oldText, newText) -> {
if (! checkText2(newText)) {
// sanity check:
if (checkText2(oldText)) {
text2.set(oldText);
}
}
});
}
public StringProperty text2Property() {
return text ;
}
public final void setText2(String text2) {
text2Property().set(text2);
}
public final String getText2() {
return text2Property().get();
}
}
In general I dislike validation by listening for an invalid value and reverting like this, because other listeners to the property will see all the changes, including changes to and from invalid values. However, this might be the best option in this case.
Finally, you could consider vetoing invalid changes as in the first option, and also setting a TextFormatter on the control in the cell that simply doesn't allow text entry that results in an invalid string. This isn't always possible from a usability perspective (e.g. if empty strings are invalid, you almost always want to allow the user to temporarily delete all the text), and it means keeping two validation checks in sync in your code, which is a pain.
I have found this code for searching for a specific user, using Parse. But when i run the code, it crashes.
What is wrong with the code???
The following is the link to the codes https://teamtreehouse.com/forum/tutorial-adding-search-to-ribbit-app
Here is the code
package com.twaa9l.isnap;
import java.util.List;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import com.parse.FindCallback;
import com.parse.ParseException;
import com.parse.ParseQuery;
import com.parse.ParseRelation;
import com.parse.ParseUser;
import com.parse.SaveCallback;
public class EditFriendsActivity extends ListActivity {
public static final String TAG = EditFriendsActivity.class.getSimpleName();
protected List<ParseUser> mUsers;
protected ParseRelation<ParseUser> mFriendsRelation;
protected ParseUser mCurrentUser;
protected EditText sUsername;
protected Button mSearchButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_edit_friends);
// Show the Up button in the action bar.
setupActionBar();
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}
#Override
protected void onResume() {
super.onResume();
mCurrentUser = ParseUser.getCurrentUser();
mFriendsRelation = mCurrentUser.getRelation(ParseConstants.KEY_FRIENDS_RELATION);
sUsername = (EditText)findViewById(R.id.searchFriend);
mSearchButton = (Button)findViewById(R.id.searchButton);
///////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////The New Code for Search Users by Username///////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
mSearchButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Get text from each field in register
String username = sUsername.getText().toString();
//String password = mPassword.getText().toString();
///Remove white spaces from any field
/// and make sure they are not empty
username = username.trim();
//password = password.trim();
//Check if fields not empty
if(username.isEmpty()){
AlertDialog.Builder builder = new AlertDialog.Builder(EditFriendsActivity.this);
builder.setMessage(R.string.login_error_message)
.setTitle(R.string.login_error_title)
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
else{
//Login User
setProgressBarIndeterminateVisibility(true);
ParseQuery<ParseUser> query = ParseUser.getQuery();
query.whereEqualTo("username", username);
query.orderByAscending(ParseConstants.KEY_USERNAME);
query.setLimit(200);
query.findInBackground(new FindCallback<ParseUser>() {
#Override
public void done(List<ParseUser> users, ParseException e) {
setProgressBarIndeterminateVisibility(false);
if(e == null){
//Success we have Users to display
//Get users match us
mUsers = users;
//store users in array
String[] usernames = new String[mUsers.size()];
//Loop Users
int i = 0;
for(ParseUser user : mUsers){
usernames[i] = user.getUsername();
i++;
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
EditFriendsActivity.this,
android.R.layout.simple_list_item_checked,
usernames
);
setListAdapter(adapter);
addFriendCheckmarks();
}
else{
//No Users to Display
Log.e(TAG, e.getMessage());
AlertDialog.Builder builder = new AlertDialog.Builder(EditFriendsActivity.this);
builder.setMessage(e.getMessage())
.setTitle(R.string.error_title)
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
}
});
}
}
});
}
/**
* Set up the {#link android.app.ActionBar}.
*/
private void setupActionBar() {
getActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
if(getListView().isItemChecked(position)){
//Add Friends
mFriendsRelation.add(mUsers.get(position));
}
else{
//Remove Friend
mFriendsRelation.remove(mUsers.get(position));
}
mCurrentUser.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if(e != null){
Log.e(TAG, e.getMessage());
}
}
});
}
private void addFriendCheckmarks(){
mFriendsRelation.getQuery().findInBackground(new FindCallback<ParseUser>() {
#Override
public void done(List<ParseUser> friends, ParseException e) {
if(e == null){
//List Returned - look for a match
for(int i = 0; i < mUsers.size(); i++){
ParseUser user = mUsers.get(i);
for(ParseUser friend : friends){
if(friend.getObjectId().equals(user.getObjectId())){
//we have a match
getListView().setItemChecked(i, true);
}
}
}
}
else{
Log.e(TAG, e.getMessage());
}
}
});
}
}