I'm writing a DialogFragment for browsing the filesystem, which works really nice by now. I just got one Problem.
The files are shown in an ListView, and when the user selects a file, this event is send to the Activity that has called the Fragment over an OnFileSelectedListener-Interface. This is fine for files, but it feels wrong to send out the directory names to the activity, then destroying and recreating the Fragment, when all that should happen is that the Fragment should show a new Directory. It also makes the whole Fragement disapearing and then reapearing which isn't really nice and smooth.
Furthermore every Activity using the Fragment has to use the logic for recreating the Fragment, which is far from "don't repeat yourself".
So, in short, is there a way to do a changeout of the Listview within the Fragment? Calling the AlertDialog.Builder more than once sadly doesn't work.
Heres my DialogFragment. I hope it's ok to post the whole thing:
package de.fusionsystems.firmenlaufmonitor;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class FileChooserFragment extends DialogFragment {
private OnFileSelectedListener mCallback;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return createDialog();
}
private AlertDialog createDialog(){
// Create the AlertDialog object and return it
SharedPreferences options = PreferenceManager.getDefaultSharedPreferences(getActivity());
ArrayList<File> files = getFilesInDir(options.getString("BaseDir", ""));
ArrayList<ListEntry> fileEntries = new ArrayList<ListEntry>();
if (!isBaseDir(options.getString("BaseDir", ""))){
fileEntries.add(new ListEntry("..", getResources().getDrawable( R.drawable.ic_folder)));
}
for (File file : files){
if (file.isDirectory()){
fileEntries.add(new ListEntry(file.getName(),getResources().getDrawable(R.drawable.ic_folder)));
}else{
if (file.getName().endsWith(".kml")){
fileEntries.add(new ListEntry(file.getName(),getResources().getDrawable( R.drawable.ic_file)));
}
}
}
final FileAdapter adapter = new FileAdapter(getActivity(), fileEntries);
OnClickListener clickListener = new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String path;
SharedPreferences options = PreferenceManager.getDefaultSharedPreferences(getActivity());
if (adapter.getItem(which).name.equals("..")){
//navigate back
path = options.getString("BaseDir", "/");
path=path.substring(0, path.length());
path=path.substring(0,path.lastIndexOf("/"));
path = !path.equals("")?path:("/");
}else {
path = options.getString("BaseDir", "");
path += ((path.equals("/"))?(""):("/"))+adapter.getItem(which).name;
}
Log.d("Path", path);
Editor editor = options.edit();
File dirTest = new File(path);
if (dirTest.isDirectory()){
editor.putString("BaseDir", path);
editor.commit();
//mCallback.onFileSelected("");
//createDialog();
//*******************DO THE RIGHT THING HERE***********************
}else{
mCallback.onFileSelected(path);
}
}
};
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setAdapter(adapter, clickListener)
.setNegativeButton("Abbrechen", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dismiss();
}
});
builder.setTitle("Datei wählen");
return builder.create();
}
private ArrayList<File> getFilesInDir(String dir) {
File folder = new File(dir);
if (!folder.exists()){
folder = new File("/");
if (!folder.exists()){
Log.e("FileBrowser","Something's really fishy");
}
}
ArrayList<File> fileList = new ArrayList<File>(Arrays.asList(folder.listFiles()));
return fileList;
}
private boolean isBaseDir(String dir) {
File folder = new File(dir);
if (!folder.exists()){
folder = new File("/");
if (!folder.exists()){
Log.e("FileBrowser","Something's really fishy");
}
}
File baseDir = new File("/");
if (folder.equals(baseDir)){
return true;
}else{
return false;
}
}
// Container Activity must implement this interface
public interface OnFileSelectedListener {
public void onFileSelected(String file);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnFileSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
class ListEntry {
public String name;
public Drawable item ;
public ListEntry(String name, Drawable item) {
this.name = name;
this.item = item;
}
}
class FileAdapter extends ArrayAdapter<ListEntry>{
public FileAdapter(Context context, ArrayList<ListEntry> fileEntry) {
super(context, R.layout.filechooser_list_item,fileEntry);
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
ListEntry entry = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.filechooser_list_item, parent, false);
}
// Lookup view for data population
TextView filechooserEntry = (TextView) convertView.findViewById(R.id.filechooser_entry);
// Populate the data into the template view using the data object
filechooserEntry.setText(entry.name);
filechooserEntry.setCompoundDrawablesWithIntrinsicBounds(entry.item, null, null, null);
// Return the completed view to render on screen
return convertView;
}
}
}
Here's my solution for a Filebrowser as a DialogFragment. It turns out there are methods to add() remove() and clean() items to the adapter, so the answer to the initial question was real simple. The tricky part was to prevent the Dialog from closing after selecting a List item. This answer helped a lot: https://stackoverflow.com/a/15619098/3960095. Here's my working code for future visitors:
package de.yourCompany.yourProject;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class FileChooserFragment extends DialogFragment{
private OnFileSelectedListener mCallback;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Create the AlertDialog object and return it
final FileAdapter adapter = new FileAdapter(getActivity(), new ArrayList<ListEntry>());
adapter.getFiles();
OnClickListener clickListener = new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//do nothing here to prevent dismiss after click
}
};
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setAdapter(adapter, clickListener)
.setNegativeButton("Abbrechen", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
builder.setTitle("Datei wählen");
final AlertDialog theDialog = builder.show();
theDialog.getListView().setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String path;
SharedPreferences options = PreferenceManager.getDefaultSharedPreferences(getActivity());
if (adapter.getItem(position).name.equals("..")){
//navigate back
path = options.getString("BaseDir", "/");
path=path.substring(0, path.length());
path=path.substring(0,path.lastIndexOf("/"));
path = !path.equals("")?path:("/");
}else {
//get the Slashes right and navigate forward
path = options.getString("BaseDir", "");
path += ((path.equals("/"))?(""):("/"))+adapter.getItem(position).name;
}
Editor editor = options.edit();
File dirTest = new File(path);
if (dirTest.isDirectory()){
editor.putString("BaseDir", path);
editor.commit();
adapter.clear();
adapter.getFiles();
}else{
mCallback.onFileSelected(path);
theDialog.dismiss();
}
}
});
return theDialog;
}
private boolean isBaseDir(String dir) {
File folder = new File(dir);
if (!folder.exists()){
folder = new File("/");
if (!folder.exists()){
Log.wtf("FileBrowser","Something's really fishy");
}
}
File baseDir = new File("/");
if (folder.equals(baseDir)){
return true;
}else{
return false;
}
}
// Container Activity must implement this interface
public interface OnFileSelectedListener {
public void onFileSelected(String file);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnFileSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
class ListEntry {
public String name;
public Drawable item ;
public ListEntry(String name, Drawable item) {
this.name = name;
this.item = item;
}
}
class FileAdapter extends ArrayAdapter<ListEntry>{
//show only files with the suffix FILE_SUFFIX, use "*" to show all files;
private static final String FILE_SUFFIX = ".kml";
public FileAdapter(Context context, ArrayList<ListEntry> fileEntry) {
super(context, R.layout.filechooser_list_item,fileEntry);
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
ListEntry entry = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.filechooser_list_item, parent, false);
}
// Lookup view for data population
TextView filechooserEntry = (TextView) convertView.findViewById(R.id.filechooser_entry);
// Populate the data into the template view using the data object
filechooserEntry.setText(entry.name);
filechooserEntry.setCompoundDrawablesWithIntrinsicBounds(entry.item, null, null, null);
// Return the completed view to render on screen
return convertView;
}
private FileAdapter getFiles() {
SharedPreferences options = PreferenceManager.getDefaultSharedPreferences(getActivity());
ArrayList<File> files = getFilesInDir(options.getString("BaseDir", ""));
if (!isBaseDir(options.getString("BaseDir", ""))){
this.add(new ListEntry("..", getResources().getDrawable( R.drawable.ic_folder)));
}
for (File file : files){
if (file.isDirectory()){
this.add(new ListEntry(file.getName(),getResources().getDrawable(R.drawable.ic_folder)));
}else{
if (file.getName().endsWith(FILE_SUFFIX)||FILE_SUFFIX.equals("*")){
this.add(new ListEntry(file.getName(),getResources().getDrawable(R.drawable.ic_file)));
}
}
}
return this;
}
private ArrayList<File> getFilesInDir(String dir) {
File folder = new File(dir);
if (!folder.exists()){
folder = new File("/");
if (!folder.exists()){
Log.wtf("FileBrowser","Something's really fishy");
}
}
ArrayList<File> fileList;
if (folder.listFiles()!=null){
fileList = new ArrayList<File>(Arrays.asList(folder.listFiles()));
}else{
fileList = new ArrayList<File>();
}
return fileList;
}
}
}
and in your Activity:
public class YourActivity extends Activity implements FileChooserFragment.OnFileSelectedListener{
#Override
public void onFileSelected(String file) {
//Do whatever you want to do with the files
}
// And whereever you want to start the Fragment:
FileChooserFragment fileFragment = new FileChooserFragment();
fileFragment.show(getFragmentManager(), "fileChooser");
Related
In my app, I am trying to add sorting such as: sort by popular, top rated, etc.
with sorting options in AlertDialog.
My problem is that choosing the option to sort by GridView doesn't update or change ImageView
I tried the following but it doesn't work:
adapter.notifyDataSetChanged();
gridView.invalidateViews();
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Point;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.BoolRes;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.StringRequest;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
/**
* Created by macbook on 9/18/17.
*/
public class MoviesFragment extends Fragment implements AdapterView.OnItemClickListener {
static GridView gridView;
static int width;
static ArrayList<String> posters;
private final static String API_KEY = "0000000000000000000";
final static String URL_BASE = "https://api.themoviedb.org/3/movie/";
static String url_sorted ="popular?api_key=" ;
ImageAdapter adapter;
public MoviesFragment()
{
}
// inflate view and init grideView with set adapter
#Nullable
#Override
public View onCreateView (LayoutInflater inflater, #Nullable ViewGroup
container, #Nullable Bundle savedInstanceState){
View view = inflater.inflate(R.layout.movies_fragment, container, false);
setHasOptionsMenu(true);
// getwidth
WindowManager wm = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
if(MainActivity.TABLET)
{
width = size.x/6;
}else
{
width = size.x/2;
}
if(getActivity() != null)
{
posters = new ArrayList<String>();
adapter = new ImageAdapter(getActivity(),posters,width);
gridView = (GridView)view.findViewById(R.id.grideView);
gridView.setAdapter(adapter);
gridView.setColumnWidth(width);
gridView.setOnItemClickListener(this);
}
return view;
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getActivity(),position+"",Toast.LENGTH_SHORT).show();
}
#Override
public void onStart() {
super.onStart();
getActivity().setTitle("Most Popular Movies");
loadPoster(url_sorted);
}
public void loadPoster(String url) {
if (isNetworkAvailable()) {
gridView.setVisibility(View.VISIBLE);
getJsonImageUrl(url);
} else {
gridView.setVisibility(View.GONE);
TextView text = new TextView(getActivity());
RelativeLayout relativeLayout = (RelativeLayout) getActivity().findViewById(R.id.relative);
text.setText("no Internet Connection...");
relativeLayout.addView(text);
}
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
public Boolean getJsonImageUrl( String urlSort)
{
Toast.makeText(getActivity(),urlSort,Toast.LENGTH_LONG).show();
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, URL_BASE + urlSort+ API_KEY, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
int count = 0 ;
JSONArray obj = null;
try {
obj = response.getJSONArray("results");
} catch (JSONException e) {
e.printStackTrace();
}
while(count <obj.length())
{
JSONObject jsonObject = null;
String imgURL = null;
try {
jsonObject = obj.getJSONObject(count);
imgURL = jsonObject.getString("poster_path");
} catch (JSONException e) {
e.printStackTrace();
}
posters.add(imgURL);
count++;
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(),"ERROR",Toast.LENGTH_LONG).show();
}
}
);
Mysingleton.getInstence(getContext()).addToRequestque(jsonObjectRequest);
return true;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId())
{
case R.id.preferncesMenu:
break;
case R.id.filter:
// Intent i = new Intent(getActivity().getApplication(),SettingAactivity.class);
//startActivity(i);
showSortDialog();
break;
}
return false;
}
private void showSortDialog() {
final CharSequence[] sortBy = new String[] {"Popular", "Top Rated","Latest","Upcoming","Now playing"};
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Sort by");
builder.setSingleChoiceItems(sortBy, -1, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String newUrl;
gridView.setAdapter(null);
switch(which)
{
case 0:
newUrl = "popular?api_key=";
getActivity().setTitle("Most Popular Movies");
//loadPoster(newUrl);
break;
case 1:
newUrl = "top_rated?api_key=";
getActivity().setTitle("Top Rated Movies");
adapter.notifyDataSetChanged();
gridView.invalidateViews();
loadPoster(newUrl);
Toast.makeText(getActivity(),newUrl,Toast.LENGTH_LONG).show();
dialog.dismiss();
break;
case 2:
url_sorted = "latest?api_key=";
getActivity().setTitle("latest Movies");
break;
case 3:
url_sorted = "upcoming?api_key=";
getActivity().setTitle("UpComing Movies");
break;
case 5:
url_sorted = "now_playing?api_key=";
getActivity().setTitle("Now Playing Movies");
break;
}
}
});
builder.create().show();
}
}
The problem was calling notifyDataSetChanged() from a non UI Thread.
So after call notifyDataSetChanged() from UI Thread its work perfectly
Code:
public void refresh()
{
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
gridView.invalidate();
}
});
}
Basically inside your adapter you need to have mechanism to pass in/update the data object.
Add a method inside your adapter class which will be called when new data is available.
public void swapItems(List<Item> itemsList){
mItemsList.clear();
mItemsList.addAll(itemsList);
notifyDataSetChanged();
}
Then from your activity, after you have received your new data, just call this method from your adapter instance.
adapter.swapItems(newItemsList);
Just change the above code to match your data type. But that's basically how it's done. And if you want to be more fancy explore Android data binding.
I only see you calling notifyDataSetChanged after you set the adapter to null. I'm not sure why you would set the adapter to null and then attempt to use it. You should be crashing, not just seeing data not updated.
After your getjson call you should be calling notifyDataSetChanged to show all the new items you got. If sort is to change the sort order, then you should implement your sort on the list, then call notifyDataSetChanged again.
I'm not sure why you are nulling it out. If you do this, you should be fine.
In this activity I have an implementaion with AppCompatCallback and a delegate who set my toolbar , I have this thing for other 2 activitys and works fine , but here i get an error to the line delegate1.setSupportActionBar(toolbar).. I don't understand why...
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatCallback;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
public class AlbumActivity extends Activity implements AppCompatCallback {
private final int REQUEST_CODE_CAMERA_IMAGE = 1000;
private final int REQUEST_CODE_EXTERNAL_IMAGE = 2000;
private AppCompatDelegate delegate1;
String nameAlbum;
// Declare variables
private String[] FilePathStrings;
private String[] FileNameStrings;
private File[] listFile;
GridView grid;
GridViewAdapter adapter;
File file;
boolean deleted;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
delegate1 = AppCompatDelegate.create(this, this);
//call the onCreate() of the AppCompatDelegate
delegate1.onCreate(savedInstanceState);
//use the delegate to inflate the layout
delegate1.setContentView(R.layout.album_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.mytoolbarr);
delegate1.setSupportActionBar(toolbar);
delegate1.setTitle("Your Pictures");
Button btnChoosePicture = (Button) findViewById(R.id.addimage);
Intent intent = getIntent();
nameAlbum = intent.getStringExtra("nameAlbum");
// Check for SD Card
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
Toast.makeText(this, "Error! No SDCARD Found!", Toast.LENGTH_LONG)
.show();
} else {
// Locate the image folder in your SD Card
file = new File(Environment.getExternalStorageDirectory()
+ File.separator + nameAlbum);
if (file.isDirectory()) {
listFile = file.listFiles();
// Create a String array for FilePathStrings
FilePathStrings = new String[listFile.length];
// Create a String array for FileNameStrings
FileNameStrings = new String[listFile.length];
for (int i = 0; i < listFile.length; i++) {
// Get the path of the image file
FilePathStrings[i] = listFile[i].getAbsolutePath();
// Get the name image file
FileNameStrings[i] = listFile[i].getName();
}
}
// Locate the GridView in gridview_main.xml
grid = (GridView) findViewById(R.id.gridview);
// Pass String arrays to LazyAdapter Class
adapter = new GridViewAdapter(this, FilePathStrings, FileNameStrings);
// Set the LazyAdapter to the GridView
grid.setAdapter(adapter);
// Capture gridview item click
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent i = new Intent(AlbumActivity.this, ViewImage.class);
// Pass String arrays FilePathStrings
i.putExtra("filepath", FilePathStrings);
// Pass String arrays FileNameStrings
i.putExtra("filename", FileNameStrings);
// Pass click position
i.putExtra("position", position);
startActivity(i);
}
});
grid.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, final View view, final int position, final long id) {
AlertDialog.Builder builder = new AlertDialog.Builder(AlbumActivity.this);
builder.setCancelable(true);
builder.setMessage("Are you sure you want to delete this picture ?");
builder.setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
File filepath = Environment.getExternalStorageDirectory();
File dir5 = new File(filepath.getAbsolutePath()
+ nameAlbum+FileNameStrings[position]);
File file3 = new File(String.valueOf(dir5));
deleted = file3.delete();
adapter.notifyDataSetChanged();
finish();
startActivity(getIntent());
dialog.dismiss();
}
});
builder.setTitle("Delete Picture");
AlertDialog dialog = builder.create();
dialog.show();
return true;
}
});
}
//select picture from external storage
btnChoosePicture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// choose picture from gallery
Intent PhotoPickerIntent = new Intent(
Intent.ACTION_PICK);
File pictureDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
String pictureDirectoryPath = pictureDirectory.getPath();
Uri data = Uri.parse(pictureDirectoryPath);
PhotoPickerIntent.setDataAndType(data, "image/*");
startActivityForResult(PhotoPickerIntent,
REQUEST_CODE_EXTERNAL_IMAGE);
}
});
}
#Override
but here i get an error to the line delegate1.setSupportActionBar(toolbar)
It can be two differents things :
You've imported android.widget.Toolbar instead of android.support.v7.widget.Toolbar
Your Activity has to extends AppCompatActivity if you want to use setSupportActionBar(toolbar)
If you extends AppCompatActivity you have to use Theme.AppCompat.Light.NoActionBar
#Skizo here everything works fine and extends Activity...
public class EnterDataActivity extends Activity implements AppCompatCallback {
private AppCompatDelegate delegate;
EditText editTextPersonName;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
delegate = AppCompatDelegate.create(this, this);
//call the onCreate() of the AppCompatDelegate
delegate.onCreate(savedInstanceState);
//use the delegate to inflate the layout
delegate.setContentView(R.layout.enter_data);
editTextPersonName = (EditText) findViewById(R.id.et_person_name);
Toolbar toolbar= (Toolbar) findViewById(R.id.mytoolbar2);
delegate.setSupportActionBar(toolbar);
delegate.setTitle("Enter Album Name");
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}else if(id==android.R.id.home){
finish();
}
return super.onOptionsItemSelected(item);
}
public void onClickAdd (View btnAdd) {
String personName = editTextPersonName.getText().toString();
if ( personName.length() != 0 ) {
Intent newIntent = getIntent();
newIntent.putExtra("tag_person_name", personName);
this.setResult(RESULT_OK, newIntent);
finish();
}
}
#Override
public void onSupportActionModeStarted(ActionMode mode) {
}
#Override
public void onSupportActionModeFinished(ActionMode mode) {
}
#Nullable
#Override
public ActionMode onWindowStartingSupportActionMode(ActionMode.Callback callback) {
return null;
}
}
I did solved my issue , I had to include my toolbar layout in my activity layout... Thank you everyone for interest in solving my issue!!
I'm Getting data from my database and pushing them into ListView to view all the data.
Inside my ListView I also have a TextView with the text "Like" in it. Now when I click the like text it will change to "Liked" and I'm updating my like status in my database.
Now my problem is that when i click the "Like" text, the text changes to "Liked" and also it is updated in DB. But also when I scroll through the List View, I can notice other lists' Like text is also changed to Liked. I'm not sure what's going wrong.
I've been trying to get around this problem for quite some days but had no success.
This is my adapter code. At the bottom you can see my onClickListener for the textview
package com.mytestapp.myapp;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class ForumAdapter extends ArrayAdapter<DiscussionList> {
private static List<DiscussionList> items = null;
public ForumAdapter(Context context, List<DiscussionList> items) {
super(context, R.layout.custom_list, items);
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
public static DiscussionList getModelPosition(int position) {
return items.get(position);
}
public void refill(List<DiscussionList> items) {
items.clear();
items.addAll(items);
notifyDataSetChanged();
}
public static class ViewHolder {
WebView mywebviewholder;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View v = convertView;
if (v == null) {
LayoutInflater li = LayoutInflater.from(getContext());
v = li.inflate(R.layout.custom_list, null);
} else {
holder = (ViewHolder) convertView.getTag();
}
DiscussionList app = items.get(position);
if (app != null) {
TextView titleText = (TextView) v.findViewById(R.id.dscTitle);
TextView categoryText = (TextView) v.findViewById(R.id.dscCategory);
TextView descriptionText = (TextView) v
.findViewById(R.id.dscDescription);
TextView timeText = (TextView) v.findViewById(R.id.dscTime);
TextView idText = (TextView) v.findViewById(R.id.dscDiscId);
final TextView likeText = (TextView) v.findViewById(R.id.likeText1);
String like_Status = app.getLikeStatus();
titleText.setText(app.getTitle());
categoryText.setText(app.getCategory());
descriptionText.setText(app.getDescription());
timeText.setText(app.getTime());
idText.setText(app.getDiscId());
if (like_Status == "null") {
likeText.setText("Like");
} else {
likeText.setText("Liked");
}
final String dId = app.getDiscId();
// onClick for image button inside list view
likeText.setTag(new Integer(position));
likeText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final Integer myposition = (Integer) view.getTag();
// Toast.makeText(getContext(), "" + dId,
// Toast.LENGTH_SHORT)
// .show();
likeText.setText("Liked");
MainActivity val = new MainActivity();
val.updateLikeTable(dId);
}
});
}
return v;
}
}
And also this is my MainActivity.java file where i update the likes in database
package com.mytestapp.myapp;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends ListActivity implements FetchDataListener {
public static String strTitle = "0", strCategory = "0",
strDescription = "0", strTime = "0", strDid = "0";
Collegemate_DB db = new Collegemate_DB(this);
int likeStatus = 1;
private ProgressDialog dialog;
public static String usId=null;
ImageButton imgButton;
List<DiscussionList> items = new ArrayList<DiscussionList>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_forum_topics);
usId = db.getCurrentuserId();
initView();
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
}
/*
* On click listener to get values from DiscussionList class and send it
* to another activity when clicking on the list item
*/
ListView forumList = getListView();
forumList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// Get position of the clicked list item from adapter
String dTitle, dCategory, dDescription, dTime, dDid;
DiscussionList accessVar = ForumAdapter
.getModelPosition(position);
dTitle = accessVar.getTitle();
dCategory = accessVar.getCategory();
dDescription = accessVar.getDescription();
dTime = accessVar.getTime();
dDid = accessVar.getDiscId();
/*
* Storing the forum values in string and passing it to another
* activity
*/
String values[] = { dTitle, dCategory, dDescription, dTime,
dDid };
Intent i = new Intent(MainActivity.this, ForumFullView.class);
i.putExtra("sendData", values);
startActivity(i);
}
});
}
private void initView() {
// show progress dialog
Log.i("j","Inside Init");
dialog = ProgressDialog.show(this, "", "Loading...");
String url = "http://example.com/mypath/listData.php?currentUser_id="
+ usId;
Log.i("Fetch Url : ", url);
FetchDataTask task = new FetchDataTask(this);
task.execute(url);
}
#Override
public void onFetchComplete(List<DiscussionList> data) {
// dismiss the progress dialog
if (dialog != null)
dialog.dismiss();
// create new adapter
ListView forumList = getListView();
// set the adapter to list
ForumAdapter adapter = new ForumAdapter(this, data);
if (forumList.getAdapter() == null) {
//final ForumAdapter adapter = new ForumAdapter(this, data);
forumList.setAdapter(adapter);
} else {
((ForumAdapter) forumList.getAdapter()).refill(items);
}
// setListAdapter(adapter);
}
#Override
public void onFetchFailure(String msg) {
// dismiss the progress dialog
if (dialog != null)
dialog.dismiss();
// show failure message
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
public void updateLikeTable(String dId,List<DiscussionList> items) {
try {
String likeUrl = "http://example.com/mypath/createlike.php?discId="
+ dId + "&userId=" + usId + "&like_status=" + likeStatus;
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet();
request.setURI(new URI(likeUrl));
client.execute(request);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Any help is appreciated.
Thanks in advance
The problem you're having is that the ListView widget recycles its views if it can. Once a view is off the screen from scrolling, it goes onto a garbage heap so that when a new view scrolls into place it can be reused, rather than requiring a fresh one to be inflated from scratch. That recycled view is the convertView parameter in the getView() method. When your ListView is first populating, convertView will always be null, since the garbage pile has nothing in it, so you're forced to inflate new views, but subsequent calls will likely have that parameter as non-null.
The practical result of this is that when a clicked view that's been set to "Liked" gets recycled, the TextView is still there and still populated with "Liked" rather than the presumed default of "Like". So if you click a view, then scroll down so it goes off the screen, it'll come back around and cause the bug you're seeing.
What you'll probably want to do to fix this is to set the text of likeText within getView() every time, based on what it is in your database. If the post has been liked, set it to "Liked", and if it hasn't, set it to "Like". It should just be one more line, assuming you have easy access to whether or not the post is liked from your DiscussionList object.
P.S. As a side note, hard-coded strings are typically frowned upon in Android, so you may want to move your "Liked" string into the resource files. It's not really necessary unless you're planning to do translations, but it's still good practice.
i have already searched high and low on the net.
tried several tips and tutorials but none is really working for me.
What i am trying to do is using a multiple choicelist to delete more than 1 entry in my list.
everything is working, and the list is set to multiplechoice in the xml, but when trying to update my custom list i can't seem to fix that recycling.
I am using a resourcecursoradapter, no idea if that is the problem or not, but i'm at a loss right now, so if any body could help me that would be great.
Now for the code of my Activity.
package com.ShaHar91.ivlibrary;
import java.io.IOException;
import java.io.InputStream;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.database.SQLException;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.ResourceCursorAdapter;
import android.widget.TextView;
import android.widget.Toast;
#SuppressWarnings("deprecation")
public class DeleteMultiPoke extends ListActivity {
public static final String ROW_ID = "row_id"; // Intent extra key
private long rowID;
MyAdapter mListAdapter;
Menu menu;
MenuItem delete;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
DatabaseConnector myDbHelper = new DatabaseConnector(
DeleteMultiPoke.this);
try {
myDbHelper.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
try {
DatabaseConnector.openDataBase();
} catch (SQLException sqle) {
throw sqle;
}
Cursor myCur = null;
myCur = myDbHelper.getAllPokes();
mListAdapter = new MyAdapter(DeleteMultiPoke.this, myCur);
setListAdapter(mListAdapter);
}
private class MyAdapter extends ResourceCursorAdapter {
public MyAdapter(Context context, Cursor cur) {
super(context, R.layout.poke_list_remove_item, cur);
}
#Override
public View newView(Context context, Cursor cur, ViewGroup parent) {
LayoutInflater li = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return li.inflate(R.layout.poke_list_remove_item, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cur) {
TextView pokeTv = (TextView) view.findViewById(R.id.pokeTv);
TextView genderTv = (TextView) view.findViewById(R.id.genderTv);
RadioButton hpRb = (RadioButton) view.findViewById(R.id.hpRb);
RadioButton attRb = (RadioButton) view.findViewById(R.id.attRb);
RadioButton defRb = (RadioButton) view.findViewById(R.id.defRb);
RadioButton spAttRb = (RadioButton) view.findViewById(R.id.spAttRb);
RadioButton spDefRb = (RadioButton) view.findViewById(R.id.spDefRb);
RadioButton speedRb = (RadioButton) view.findViewById(R.id.speedRb);
ImageView pokeSprite = (ImageView) view
.findViewById(R.id.pokeSpriteIV);
pokeTv.setText(cur.getString(cur.getColumnIndex("name")));
genderTv.setText(cur.getString(cur.getColumnIndex("gender")));
hpRb.setChecked((cur.getInt(cur.getColumnIndex("hp")) == 0 ? false
: true));
attRb.setChecked((cur.getInt(cur.getColumnIndex("att")) == 0 ? false
: true));
defRb.setChecked((cur.getInt(cur.getColumnIndex("def")) == 0 ? false
: true));
spAttRb.setChecked((cur.getInt(cur.getColumnIndex("sp_att")) == 0 ? false
: true));
spDefRb.setChecked((cur.getInt(cur.getColumnIndex("sp_def")) == 0 ? false
: true));
speedRb.setChecked((cur.getInt(cur.getColumnIndex("speed")) == 0 ? false
: true));
AssetManager assetManager = getAssets();
int imageIndex = cur.getColumnIndex("nat_dex");
try {
InputStream ims = assetManager.open("pokes/"
+ cur.getString(imageIndex) + ".gif");
Drawable d = Drawable.createFromStream(ims, null);
pokeSprite.setImageDrawable(d);
} catch (IOException ex) {
return;
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.poke_menu_remove, menu);
delete = menu.findItem(R.id.deletepokes);
delete.setEnabled(false);
delete.setVisible(false);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.canceldeleting:
finish();
return true;
case R.id.deletepokes:
// create a new AlertDialog Builder
AlertDialog.Builder builder = new AlertDialog.Builder(
DeleteMultiPoke.this);
builder.setTitle(R.string.confirmTitle); // title bar string
builder.setMessage(R.string.confirmMessage); // message to display
// provide an OK button that simply dismisses the dialog
builder.setPositiveButton(R.string.button_delete,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int button) {
final DatabaseConnector databaseConnector = new DatabaseConnector(
DeleteMultiPoke.this);
ListView listView = (ListView) findViewById(android.R.id.list);
SparseBooleanArray checked = listView
.getCheckedItemPositions();
for (int i = checked.size() - 1; i >= 0; i--) {
final int position = checked.keyAt(i);
if (checked.valueAt(i)) {
AsyncTask<Long, Object, Object> deleteTask = new AsyncTask<Long, Object, Object>() {
#Override
protected Object doInBackground(
Long... params) {
databaseConnector.deletePoke(mListAdapter
.getItemId(position));
return null;
}
#Override
protected void onPostExecute(
Object result) {
finish(); // return to the
// BookLibrary Activity
}
};
// delete the AsyncTask to delete book at
// rowID
deleteTask.execute(new Long[] { rowID });
}
}
} // end method onClick
});
builder.setNegativeButton(R.string.button_cancel, null);
builder.show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
protected void onResume() {
super.onResume();
mListAdapter.getCursor().requery();
}
#Override
protected void onStop() {
super.onStop();
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
String selected = "";
int cntChoice = l.getCount();
SparseBooleanArray sparseBooleanArray = l.getCheckedItemPositions();
for (int i = 0; i < cntChoice; i++) {
if (sparseBooleanArray.get(i)) {
selected += l.getItemAtPosition(i).toString() + "\n";
}
}
Toast.makeText(DeleteMultiPoke.this,
selected,
Toast.LENGTH_LONG).show();
if (l.getCheckedItemCount() == 0) {
delete.setEnabled(false);
delete.setVisible(false);
} else {
delete.setEnabled(true);
delete.setVisible(true);
}
}
Ty in advance,
Christiano Bolla
You should notify the list that the underlying data source has changed by calling notifyDataSetChanged() on your list adapter after deleting any item.
I'm doing some background processing in my activity and have a ListView that shows the progress. I 'update' the listView with
adapter.notifyDataSetChanged();
However when I leave the activity and then come back, the background processes are still running, but the list view isn't updated. This is presumably because it's a new object, not the previous one. How do I maintain my list view object between activity loads?
This is my activity. I think the issue is that the 'adapter' variable that the download uses to bind to to show updates, is recreated in the onCreate method of the activity, and the 'adapter' variable that the download originally bound to is not in the activity anymore.
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.model.ProgressEvent;
import com.amazonaws.services.s3.model.ProgressListener;
import com.amazonaws.services.s3.transfer.TransferManager;
//import com.amazonaws.auth.AWSCredentials;
//import com.amazonaws.auth.BasicAWSCredentials;
public class VideosActivity extends Activity {
ListView video_list;
CustomList adapter;
File storage_dir;
SharedPreferences completed_downloads; //http://developer.android.com/guide/topics/data/data-storage.html
SharedPreferences downloaded_data; //maps position to percent downloaded
SharedPreferences queue; //holds which fiiles are awaiting download
String images[]; //holds references to all thumnails for vids
String volume; //something like vol1 or vol2
String s3_dir; //the directory after the boucket that the files are stored in (do not add first slash)
String s3_bucket = "com--apps";
Handler handler = new Handler(); //'tunnel' through whci other threads communicate with main thread
Map<String, String[][]> video_config = new HashMap<String, String[][]>(); //holds info about video thumbs and filenames for all apps
ArrayList<String> arr_videos = new ArrayList<String>(); //holds video names
DownloadQueue queue_manager = new DownloadQueue();
#Override
public void onCreate(Bundle savedInstanceState) {
Log.v("dev", "onCreateCalled");
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
volume = getPackageName().split("\\.")[2]; //something like vol1 or vol2
s3_dir = "android/" + volume + "/"; //the directory after the boucket that the files are stored in (do not add first slash)
completed_downloads = getSharedPreferences("completed_downloads", 0);
downloaded_data = getSharedPreferences("downloaded_data", 0);
queue = getSharedPreferences("queue", 0);
storage_dir = getApplicationContext().getExternalFilesDir(null); //private to app, removed with uninstall
adapter = new CustomList(this, R.layout.customlist, arr_videos);
video_list = (ListView)findViewById(R.id.list);
video_list.setAdapter(adapter); //set adapter that specifies list contents
ensureStorageDirExists( storage_dir ); //make sure storage dir exists
set_video_data(); //store vid dat in array
ensure_connection_or_warn();
}
public boolean ensure_connection_or_warn()
{
if(have_connection())
{
return true;
}
else
{
Toast.makeText(this, "No Internet connection", Toast.LENGTH_LONG).show();
return false;
}
}
protected void ensureStorageDirExists( File dir )
{
if (!dir.exists())
{
dir.mkdirs();
}
}
public void set_video_data()
{
config_video_data(); //run config
images = video_config.get(getPackageName())[0]; //set images
for (String name : video_config.get(getPackageName())[1] ) { //set video info, this should be streamlined but is due to legacy code and my crap Java skills, consider doing like this: http://developer.android.com/guide/topics/resources/more-resources.html#TypedArray
arr_videos.add(name);
}
}
public SharedPreferences stored_vals()
{
return PreferenceManager.getDefaultSharedPreferences(this);
}
public boolean have_connection()
{
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if(cm.getActiveNetworkInfo()!=null && cm.getActiveNetworkInfo().isConnected() && cm.getActiveNetworkInfo().isAvailable())
{
Log.v("dev", "have internet connection");
return true;
}
else
{
Log.v("dev", "No internet connection");
return false;
}
}
public class DownloadQueue
{
protected void process()
{
if (queue.size() > 0 && queue.get(0).download_status == "queued") //this is meant to force one download at a time
{
queue.get(0).start();
adapter.notifyDataSetChanged();
}
}
protected void add(Integer position)
{
queue.edit.putInt(position+"");
d.download_status = "queued";
adapter.notifyDataSetChanged();
}
protected boolean position_is_queued(Integer position)
{
for (Download d : queue ) {
if(d.position == position)
{
return true;
}
}
return false;
}
protected void remove(Download d)
{
queue.remove(d);
adapter.notifyDataSetChanged();
}
}
public class CustomList extends ArrayAdapter<String>
{
View view;
int position;
Button btn;
public CustomList(Context context, int layout_id, ArrayList<String> objects)
{
super(context, layout_id, objects);
}
#Override
public View getView(final int position, View convertView, ViewGroup view_group)
{
set_view(convertView);
this.position = position;
TextView text_view = (TextView) view.findViewById(R.id.name);
ImageView image = (ImageView) view.findViewById(R.id.img);
btn = (Button) view.findViewById(R.id.play);
prepare_btn();
text_view.setText( list_text() );
image.setImageResource(
getResources().getIdentifier(images[position], "drawable", getPackageName())
);
return view;
}
public String list_text()
{
String s = arr_videos.get( position ).replace("_", " ").replace(".m4v", "");
s = s.substring(2, s.length());
return s;
}
public void set_view(View convertView)
{
if(convertView == null)
{
LayoutInflater inflater = getLayoutInflater();
view = inflater.inflate(R.layout.customlist, null);
}
else
{
view = convertView;
}
}
public Boolean is_downloaded()
{
return completed_downloads.getBoolean(position + "", false);
}
public void prepare_btn()
{
btn.setTag((Integer) position);
if(is_downloaded() == true)
{
btn.setText("Play ");
btn.setEnabled(true);
btn.setOnClickListener( new OnClickListener()
{
public void onClick(View btn)
{
int position = (Integer) btn.getTag();
Intent i = new Intent(VideosActivity.this, PlayVideoActivity.class);
String video_path = storage_dir + "/" + arr_videos.get(position);
Log.v("video_path", video_path);
i.putExtra("video_path", video_path);
startActivity(i);
}
});
}
else if( downloaded_data.contains(position+"") ) //it it's currently being downloaded
{
btn.setText(downloaded_data.getInt(position+"", 0) + "%");
btn.setEnabled(false);
}
else if( queue_manager.position_is_queued(position) ) //it's in the queue
{
btn.setText("Queued");
btn.setEnabled(false);
}
else
{
btn.setText("Download");
btn.setEnabled(true);
btn.setOnClickListener( new OnClickListener()
{
public void onClick(View btn)
{
int position = (Integer) btn.getTag();
btn.setEnabled(false);
queue_manager.add(position);
}
});
}
}
}
public class Download
{
File new_video_file;
int position;
String download_status;
com.amazonaws.services.s3.transfer.Download download;
protected void queue(int position)
{
this.position = position;
queue_manager.add(this);
queue_manager.process();
//put this download in the queue
//start downloading if it's the only one in the queue
}
protected void start()
{
if(!ensure_connection_or_warn())
{
return;
}
this.download_status = "started";
this.new_video_file = new File(storage_dir, arr_videos.get(position)); //local file to be writtent to
TransferManager tx = new TransferManager(credentials);
//http://stackoverflow.com/questions/6976317/android-http-connection-exception
this.download = tx.download(s3_bucket, s3_dir + arr_videos.get(position), new_video_file);
download.addProgressListener(new ProgressListener()
{
public void progressChanged(final ProgressEvent pe)
{
handler.post( new Runnable()
{
#Override
public void run()
{
if ( pe.getEventCode() == ProgressEvent.COMPLETED_EVENT_CODE )
{
Download.this.onComplete();
}
else
{
Download.this.onProgressUpdate();
}
}
});
}
});
}
//protected void onProgressUpdate(Double progress)
protected void onProgressUpdate()
{
this.download_status = "downloading";
Double progress = this.download.getProgress().getPercentTransfered();
Integer percent = progress.intValue();
//Log.v("runnable", percent + "");
downloaded_data.edit().putInt(position+"", percent).commit();
adapter.notifyDataSetChanged();
}
protected void onComplete()
{
Log.v("dev", "download complete!!!");
//downloaded_data.remove(position);
this.download_status = "complete";
completed_downloads.edit().putBoolean(position + "", true).commit();
queue_manager.remove(this);
queue_manager.process();
adapter.notifyDataSetChanged();
// this.download.abort();
}
}
}
Not exactly sure what happens during background processing and what do you mean by ListView state, but my suggestion would be:
try the following:
#Override
protected void onResume() {
super.onResume();
yourAdapter.clear();
yourAdapter.addAll(yourData); // API level [1..10] use for(..){ yourAdapter.add(yourData.get(index)) }
yourAdapter.notifyDataSetChanged();
}
Reason:
An adapter keeps a copy of all the elements, so when you call notifyDataSetChanged, it checks its own copy of the elements