Creating a basic adapter for searchview that uses asynctask - java

So I'm making this student project Android app that I use to search movies online.
The problem I'm having is that even though there is tons of material to read, I don't quite comprehend how adapters for searchview results are supposed to be made. I know what kind of data the query returns, but I still don't know how to make an adapter for it.
I'm only at a beginner level in Java and Android programming, but this project really fired me up and I've been working on it day and night. If you have any tips (to improve my code) please do share them.
public class SearchActivity extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.searchactivity);
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
new doMySearch().execute(query);
}
}
private class doMySearch extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
String parameters = (params[0]);
JTomato jtomato = new JTomato("gibberish-cencored");
jtomato.setPage_limit(1);
List<Movie> movies = new ArrayList<Movie>();
String total = String.valueOf(jtomato.searchMovie(parameters, movies, 0));
return total;
}
#Override
protected void onPostExecute(String result) {
}
}
}
}
The data this search should return (if the search word were hulk) is as follows: [The Incredible Hulk, Hulk, HULK VS., Hulkamania Forever, Hulk Hogan's All-Time Champ, Hulk Hogan - The Missing Matches] and as many more to be found with that search word. I'm using a Java client for rotten tomatoes API that does most of the coding for me (http requests and json object parsing).

You should probably use the class ArrayAdapter.
You can convert the string you receive into an array of strings, and then create an ArrayAdapter with the list of strings. If you set that adapter as the activity's list adapter, it will show the names of the movies in the activity.

Related

How to call a method of a different activity from MainActivity in Android?

I'm making an Android App with Google Spreadsheets. I'm scanning a barcode from a book, looking the info with the Google Books API and then I need to save this info into a sheet.
The following code is inside MainActivity:
private class GetBookInfo extends AsyncTask <String, Void, String> {
#Override
protected String doInBackground(String... urls) {
// make Call to the url
makeCall("https://www.googleapis.com/books/v1/volumes?" +
"q=isbn:" + ean_content + "&AIzaSyCpYez5556X4UzPV6rF4kkspj9DsCs_Q_c");
//print the call in the console
System.out.println("https://www.googleapis.com/books/v1/volumes?" +
"q=isbn:" + ean_content + "&AIzaSyCpYez5556X4UzPV6rF4kkspj9DsCs_Q_c");
return null;
}
#Override
protected void onPreExecute() {
// we can start a progress bar here
}
#Override
protected void onPostExecute(String result) {
String ruta = save_cover(getApplicationContext(), title, book_cover);
Intent intent = new Intent(MainActivity.this, Spreadsheets.class);
finish();
startActivity(intent);
}
}
After this code I have public void makeCall(String stringURL). It searchs the book's title, author, date, description and category of the book.
I have another Activity:
public class Spreadsheets extends Activity implements EasyPermissions.PermissionCallbacks
In this activity, I have the following code to write into a Google Sheet:
public void setDataToApi (String title, String author, String date, String category, String description) throws IOException {
String spreadsheetId = "1Gg121IjABekfSTKXg_TQzJgg4boxvYIQnmf_K4YDboo";
String range = "Sheet1!A2:E2";
List<List<Object>> values = new ArrayList<>();
List<Object> data1 = new ArrayList<>();
data1.add(title);
data1.add(author);
data1.add(date);
data1.add(category);
data1.add(description);
values.add(data1);
ValueRange valueRange = new ValueRange();
valueRange.setMajorDimension("ROWS");
valueRange.setRange(range);
valueRange.setValues(values);
UpdateValuesResponse response = this.mService.spreadsheets().values().update(spreadsheetId, range, valueRange)
.setValueInputOption("RAW")
.execute();
System.out.printf("%d cells updated.", response.getUpdatedCells());
}
My problem is that I'm trying to call the setDataToApi method from the onPostExecute method, before the intent, but it does not work at all. Thank you very much!
You cannot call the method of another Activity from outside that Activity. Before the Intent is actually dispatched, the other Activity is not yet running. You either need to
Move GetBookInfo to the SpreadSheets Activity so that it can perform the onPostExecute directly in the Activity. This requires passing the book's ID via an extra on the Intent. Or...
Keep GetBookInfo where it is in MainActivity and pass all the looked up details of the book through extras on the Intent.
If you have a method being called from 2 different activities, I would recommend putting that method in a separate class. So move setDataToApi into it's own Java class, instantiate an object of your new class and use that method in both of your activities that call it.
Or, as Elan said in their answer, use intents and pass information to your other activity using putExtra and write your own logic in the onCreate method to call setDataToApi. Hope this helps!

Editing and saving an ArrayList<> that has been passed to another activity

I am making a frisbee logger and have an ArrayList of Team objects. Each Team has an ArrayList of Player objects. Everything is using Serializable properly to be sent using Intent.
In my main activity I am displaying the list of Team objects in a ListView and an option to add another Team (only a name is needed). Once a Team is selected I pass the object to another activity using Intent. On this second activity I have it display the list of Player objects and have fields to enter another player object into the passed list.
When I return to the main activity and go back to the add Player activity, what I have added is gone.
I cannot use static because there is obviously more than one Team object. I think passing back the changed ArrayList could work but that seems a little lame, time-consuming, and frustrating.
Is there a built-in way in Android Studio that does this or am I on my own?
Note: I am not using SQLite as suggested in the comments
There's not a whole lot to show on this but here it is I guess:
MainActivity.java
private static ArrayList<Team> listOfTeams = new ArrayList<>();
private static ArrayList<Game> listOfGames = new ArrayList<>();
private ListView gameList, teamList;
.....
teamList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Team t = (Team)teamList.getItemAtPosition(position);
viewTeam(t);
}
});
.....
//Item select in teamList. Start the TeamViewActivity
public void viewTeam(Team t)
{
Intent i = new Intent(this, TeamViewActivity.class);
i.putExtra("teamView",t);
startActivity(i);
}
TeamViewActivity.java
private Team team;
private ListView rosterList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_team_view);
rosterList = (ListView) findViewById(R.id.playerList);
Intent i = getIntent();
Bundle extras = i.getExtras();
if(extras!=null)
{
if(extras.get("teamView")!=null)
{
team = (Team) extras.get("teamView");
}
}
populateRosterList(team.getRoster());
}
public void addPlayerToRoster(View view)
{
String checkFirst = ((EditText) findViewById(R.id.firstText)).getText().toString();
String checkLast = ((EditText) findViewById(R.id.lastText)).getText().toString();
String checkNumber = ((EditText) findViewById(R.id.numberText)).getText().toString();
if(!checkNumber.equals(""))
{
team.addPlayer(checkFirst, checkLast, Integer.parseInt(checkNumber));
((EditText) findViewById(R.id.firstText)).setText("");
((EditText) findViewById(R.id.lastText)).setText("");
((EditText) findViewById(R.id.numberText)).setText("");
populateRosterList(team.getRoster());
}
}
public void returnToMain(View view)
{
Intent i = new Intent(this, MainActivity.class);
i.putExtra("teamView", team);
startActivity(i);
}
private void populateRosterList(ArrayList<Player> list)
{
ArrayAdapter<Player> adapter = new ArrayAdapter<>(this,
R.layout.activity_list, R.id.genericText, list);
rosterList.setAdapter(adapter);
}
Consider your concept:
You serialize an object, i.e. you transform it into a transferrable format which is then copied over to the other activity and reconstructed as a new instance.
Consequently, you alter another instance, which is not available in the previous activity, if you do not return it - again, serialized - and finally reconstruct and copy it back into the respective instance.
What you need is a shared memory storage in your application, which can alter and retrieve data cross-activity OR a proper data routing using Intents w/ ISerializable.
Options:
Always serialize objects and pass and copy them around.
-> No multithreaded alteration, possibly slow, unbeautiful
Singleton application with global data storage ir Context Object (I do NOT recommend the due to memory management and Garbage
Collection inbetween Activity Switches BUT for consistency I'd
wanted to mention this option)
SQLite3
-> Quick, Simple and Scalable, But a bit cumbersome to get started with
Any other file-structure stored and maintained in the data folder
-> I'd expect a lot of boilerplate code here, and low performance
Webservice and remote database
Proper component setup, i.e. initialize all accessing components in your software with the appropriate reference to the data structs using for example fragments (Thanks to #mismanc, I actually missed that option initially)
In general you could abstract all that away using services and repositories, which allows you to under-the-hood test options like 3. 4. And 5. and find your best solution, and in addition, keeo the accessing code simple and clean.
in your case, you can use startActivityForResult instead of startActivity, then get your modified Team object from onActivityResult(int requestCode, int resultCode, Intent data) to update your list.
startActivityForResult example
You can use fragments. You hold the list in the MainActivity and pass its reference to ShowListFragment and AddPlayerFragment by interfaces. And you can also do other operations over them. If you dont want to use json or sqlite it can be a good way for you.
MainActivity.java
public class MainActivity extends Activity implements ShowListener{
public interface ShowListener{
ArrayList<Team> getTeamList();
}
private ArrayList<Team> listOfTeams = new ArrayList<>();
#Override
public ArrayList<Team> getTeamList() {
return listOfTeams;
}
}
ShowListFragment.java
public class ShowListFragment extends Fragment {
private ArrayList<Team> listOfTeams;
private ShowListener listener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listener = (ShowListener)getActivity();
listOfTeams = listener.getTeamList();
}
}
As #Kingfisher Phuoc mentioned you could use srartActivityForResult in case you don't want to change your approach.
Otherwise I will suggest you use either :
SharedPreference to store your arraylist object (by converting the arraylist to json then store it as string in json format). In the PlayerActivity you retrieve the data, manipulate it then save it. see this post
SQLite

Linked List not updating values

So I've debugged my program and have found that the part of my program is updating, whilst another isn't.
I have a method:
public void storeApplication(String name, String item){
Application app = new Application(name, item);
peopleAttending.add(app);
}
The debugger reports that an object is contained in the LinkedList (peopleAttending).
In another method:
public void populateListView() {
int noOfPeopleAttending = peopleAttending.size();
String noPeopleAttending = String.valueOf(noOfPeopleAttending);
Toast.makeText(GuestsAttending.this, noPeopleAttending, Toast.LENGTH_SHORT).show();
}
This method can be called after the previous one and states that there isn't an object within the LinkedList.
I've checked the object references just to make sure that they are pointing at the same reference and they are.
Any help would be greatly appreciated.
EDIT: Entire Class:
public class GuestsAttending extends Activity {
private LinkedList<Application> peopleAttending = new LinkedList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_guests_attending);
populateListView();
}
public void storeApplication(String name, String item){
Application app = new Application(name, item);
peopleAttending.add(app);
}
public void populateListView() {
// GuestsAdapter adapter = new GuestsAdapter(this, peopleAttending);
// ListView listView = (ListView) findViewById(R.id.listView);
// listView.setAdapter(adapter);
peopleAttending.size();
int noOfPeopleAttending = peopleAttending.size();
String noPeopleAttending = String.valueOf(noOfPeopleAttending);
Toast.makeText(GuestsAttending.this, noPeopleAttending, Toast.LENGTH_SHORT).show();
}
Second Edit:
Java Booking Screen Method:
public void saveBookingInfo(View view) {
GuestsAttending sendApplication = new GuestsAttending();
EditText applicantNameText = (EditText) findViewById(R.id.applicantNameTextField);
EditText itemToBurnText = (EditText) findViewById(R.id.itemToBurnTextField);
String appName = applicantNameText.getText().toString();
String appItemToBurn = itemToBurnText.getText().toString();
if (appItemToBurn.isEmpty() || appName.isEmpty()) {
Toast.makeText(BookingScreen.this, "Please fill in all fields.", Toast.LENGTH_SHORT).show();
}
else {
sendApplication.storeApplication(appName, appItemToBurn);
}
}
GuestsAttending Java Class: -- See Above.
Useful hint: It's really popular to set type of List as a List<> interface from java.util package instead of LinkedList<> itself.
Anyway, i am pretty sure that storeApplication method is not automatically triggered before onCreate method ran by Activity framework. Maybe your debugger is stopoing on it in different order (because of using threads or smth), but you should to log some invoke. Try to find it out.
I've found out what the problem is:
When I submit the booking information, it runs all the necessary methods. However, when the "storeApplication()" method has finished executing, the ArrayList 'empties' all the objects out.
I only noticed this when I used breakpoint and tried running the method twice, on the second time I entered booking details, the ArrayList stated it was empty.
I'm going to see if I can try and store the ArrayList in a more secure place.

How to modify snippet text of Google Maps v2 Markers in Asynctask?

So, I have searched high and low to find an answer to this problem.
I am trying to figure out how to modify the snippet text of a marker placed on my Google Map (map api v2), in an onPostExecute() call of an asynctask. How I would like to use this in my project, is to update the snippet text once the user has clicked on a marker. Sort of like an update to the information that is pre-set already on that marker.
Example, in order of operation:
User selects a marker on my map,
Asynctask is triggered (through the onMarkerClickListener())
Asynctask preExecute() changes text of snippet to "Fetching next arrival time..."
Asynctask doInBackground() queries my database for the requested data
Asynctask postExecute() sets the selected marker snippet text to "Next: 4:15PM"
I have tried a few different methods, and have arrived at a concise and reasonable solution, but it does not work. The problem I get, is that the marker needs to be of 'final' type, and when I do that, it does not update the snippet text that is displayed to the user, however it still runs through the asynctask and completes successfully.
The following is the code I've tried:
map.setOnMarkerClickListener():
map.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
// Update marker next stop time
updateMarkerSnippet(marker);
return false;
}
});
updateMarkerSnippet():
public void updateMarkerSnippet(final Marker marker) {
final String title = marker.getTitle();
AsyncTask<Void, Void, Void> update = new AsyncTask<Void, Void, Void>() {
private String nextArrival = "";
#Override
protected Void onPreExecute() {
marker.setSnippet("Fetching next arrival time...");
}
#Override
protected Void doInBackground(Void... voids) {
nextArrival = db.getNextArrival(title); // db is my database sql class (runs queries)
return null;
}
#Override
protected void onPostExecute(Void result) {
marker.setSnippet("Next: " + nextArrival);
}
};
update.execute((Void[]) null);
}
I just don't want the map to hang while my database is sifting through hundreds of time records. Any help is much appreciated, as I'm sure this would help more than just myself.
This is a known shortcoming in the Android Google Maps API. Take a look here for some workarounds.
it is intresting because marker.setPosition works good but marker.setSnippet does not (for my custom snippet layout), I fixed it like this:
if(marker.isInfoWindowShown())
{
marker.hideInfoWindow();
marker.showInfoWindow();
}

ListView, ArrayAdapter in Android

I need some help with my class
I have to make an asynchronous call to the method getTodaysTweets()
in TweetUtil to retrieve data.
POPULAR list of data you collected.
View dialog for the app work while the asynchronous call of
TweetUtil is in progress.
Class
public class MainActivity extends Activity{
private ListView listOfTweets;
private ArrayAdapter<String> tweetsAdapter;
protected void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listOfTweets = (ListView) findViewById(R.id.listOfTweets);
tweetsAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
listOfTweets.setAdapter(tweetsAdapter);
//To:DO Get list of tweets from TweetUtil and populate list
//Do this asynchronus
}
}
public class TweetUtil{
public static List<String> getTodaysTweets(){
List<String> tweets = new ArrayList<String>();
//...getting tweets from twitter.com
//...adding the result to my List<String> tweets
return tweets;
}
}
using AsyncTask class that's will save your day and below good tutorial for it .
AsyncTask class help you to make asynchronous calling from Database or remote server and it's manage all threads you work , so you can call your method in your custom AsyncTask class –
good source for it :
http://vogella.com/articles/AndroidBackgroundProcessing/article.html

Categories