How can i retrieve data from my db and push it to my listview ?
i want use an asynctask for this.
I have used this code but my app crached every time when i run this.
idk why because when i push data to my db then it works fine. But when i retrieve then i get errors.
public class GetAsync extends AsyncTask<Void,ArrayList<Task>,String> {
private Context context;
private ListView listView;
ArrayAdapter<Task> tasks;
public GetAsync(Context context,ListView listview) {
this.context = context;
this.listView = listview;
}
#Override
protected String doInBackground(Void... voids) {
TaskDbHelper db = new TaskDbHelper(context);
tasks.addAll(db.getTasks());
return "werkt";
}
#Override
protected void onPreExecute() {
tasks = (ArrayAdapter<Task>) listView.getAdapter();
}
#Override
protected void onPostExecute(String aVoid) {
super.onPostExecute(aVoid);
}
}
lvItems = (ListView) findViewById(R.id.lvItems);
new GetAsync(this,lvItems).execute();
Try
public class GetAsync extends AsyncTask<Void,ArrayList<Task>,List<Task>> {
private Context context;
private ListView listView;
ArrayAdapter<Task> tasks;
public GetAsync(Context context, ListView listview) {
this.context = context;
this.listView = listview;
}
#Override
protected List<Task> doInBackground(Void... voids) {
TaskDbHelper db = new TaskDbHelper()
return db.getTasks();
}
#Override
protected void onPreExecute() {
tasks = (ArrayAdapter<Task>) listView.getAdapter();
}
#Override
protected void onPostExecute(List<Task> tasks) {
tasks.addAll(tasks);
}
}
It's because you are not on the UI thread whilst modifying the view. So you want to update the adapter in onPostExecute as that runs on the thread that started the AsyncTask (which I'm assuming is the UI thread)
Related
I am creating my application and I need to fill the recyclerview and then scroll to the desired item. To do this, I used AsyncTask, but the problem is that scrollToPosition () does not work. Maybe someone will tell me what I am doing wrong, since this is my first time working with AsyncTask and I do not understand what my mistake is.
public class SomeUserProfileFragment extends Fragment {
private void loadUserPosts() {
mDatabaseReference = FirebaseDatabase.getInstance().getReference().child("Posts");
new SetFirebaseRecyclerAdapter().execute();
}
class SetFirebaseRecyclerAdapter extends AsyncTask<Integer, Void, Void>
{
#Override
protected Void doInBackground(Integer... integers) {
FirebaseRecyclerOptions<TestPosts> options = new FirebaseRecyclerOptions.Builder<TestPosts>()
.setQuery(mDatabaseReference.orderByChild("uid").equalTo(uid), TestPosts.class)
.build();
mLinearLayoutManager = new LinearLayoutManager(mContext);
mLinearLayoutManager.setReverseLayout(true);
mLinearLayoutManager.setStackFromEnd(true);
adapter = new TestPostsAdapter(options, mContext);
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mRecyclerView.setAdapter(adapter);
mRecyclerView.scrollToPosition(1);
adapter.startListening();
}
}
}
I am facing strange issue during call of my activity with Fragment usage. I am getting error like,
java.lang.IllegalStateException: Fragment ScoreFragment{ee2b833
id=0x7f0e0198} not attached to Activity
On line 146. My Fragment code which have error is line like below
if(mPageFlag.equalsIgnoreCase(getString(R.string.winners))){
And My full code for same is below,
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mPageFlag = getArguments().getString(ARG_PAGE_FLAG);
}
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser && !mIsPageLoaded){
mContext = getActivity();
mIsPageLoaded = true;
if(mPageFlag.equalsIgnoreCase(getString(R.string.winners))){
new getcontestscorewinners(mContext).execute();
}else{ //
new getcontestscorewinnersNew(mContext).execute();
}
}
}
public class getcontestscorewinners extends AsyncTask<String, Void, String> {
boolean response = false;
private Context mContext;
public getcontestscorewinners(Context context) {
mContext = context;
}
#Override
protected void onPreExecute() {
progress = ProgressDialog.show(mContext, "Processing...",
"Please wait....");
}
#Override
protected String doInBackground(String... params) {
NetworkTask.getContestScoreWinners(winnerHandler);
return "";
}
#Override
protected void onPostExecute(String result) {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
Let me know if someone can help me for get out of it. Thanks.
Try using isAdded():
Return true if the fragment is currently added to its activity.
So your code should be like this :
if(isAdded() && mPageFlag.equalsIgnoreCase(getString(R.string.winners))){
i have all my async calls in their own classes and so i dont want to have global vars being set aync'ly. To do this i want to return objects eg a string from my asunc postProcess methods.
can this be done?
Below is my general structure to my classes, i want to return a String for example from onPostExecute(). I see delegates are mentioned in other places but this seems very messy, sure there is a way to have a return type to the class or methods?
class GetStuffAsyncly extends AsyncTask<String, String, String>
{
// my vars....
public myconstructor(String dialogMessage, Context con)
{
this.qDialog = new ProgressDialog(con);
this.dialogString = dialogMessage;
this.context = con;
}
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute()
{
super.onPreExecute();
do stuff like fire dialog
}
#Override
protected String doInBackground(String... args)
{
// do stuff in background...
return data;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String jsonString)
{
// dismiss the dialog after getting all data
dialog.dismiss();
}
}
Some thing like below
class GetStuffAsyncly extends AsyncTask<String, String, String> {
String dialogString;
ProgressDialog dialog;
Context context;
AsyncListener listener;
// my vars....
public GetStuffAsyncly(String dialogMessage, Context con, AsyncListener listener) {
this.dialog = new ProgressDialog(con);
this.dialogString = dialogMessage;
this.context = con;
this.listener = listener;
}
/**
* Before starting background thread Show Progress Dialog
*/
#Override
protected void onPreExecute() {
super.onPreExecute();
listener.onTaskStarted();
}
#Override
protected String doInBackground(String... args) {
// do stuff in background...
return data;
}
/**
* After completing background task Dismiss the progress dialog
**/
protected void onPostExecute(String jsonString) {
// dismiss the dialog after getting all data
dialog.dismiss();
listener.onTaskFinished(jsonString);
}
}
And the listener class
public interface AsyncListener {
void onTaskStarted();
void onTaskFinished(String data);
}
and you can call like this
new GetStuffAsyncly(message, this, new AsyncListener() {
#Override
public void onTaskStarted() {
//do your stuff
}
#Override
public void onTaskFinished(String data) {
//Do your stuff;
}
}).execute(parameter);
Another option is to use AsyncTaskLoader. You derive your class not from AsyncTask, but from AsyncTaskLoader. In your Activity you need to implement LoaderCallbacks interface. The args you want to use in Loader, you put in Bundle. All information you want to get from Loader will be passed in method onLoadFinished(). Here's an example
public class BaseInitLoader extends AsyncTaskLoader<Employee[]> {
Context mContext;
boolean firstrun;
public BaseInitLoader(Context context, Bundle args) {
super(context);
mContext = context;
firstrun = args.getBoolean("firstrun");
}
#Override
protected void onStartLoading() {
super.onStartLoading();
forceLoad();
}
#Override
public Employee[] loadInBackground() {
MainActivity activity =(MainActivity) mContext;
Cursor cursor = new DatabaseFiller(activity.getDb(), mContext, firstrun).fillTable();
ArrayList<Employee> list = new ArrayList<>();
QueryResultIterable<Employee> itr = null;
try {
itr = cupboard().withCursor(cursor).iterate(Employee.class);
for(Employee employee: itr){
list.add(employee);
}
} finally {
// close the cursor
if (itr != null) {
itr.close();
}
}
Employee[] employees = new Employee[list.size()];
employees = list.toArray(employees);
return employees;
}
}
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks, View.OnClickListener {
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
TextView priority, name, innerPhone, mobilePhone, position;
Button cityBtn;
CharSequence[] cities;
SQLiteDatabase db;
Context mContext;
private Cursor cursor;
private SQLiteDatabase database;
private ListView listView;
private TextView nameTxt;
private EmployeeAdapter adapter;
public static final String LOG_TAG = "Database";
SharedPreferences prefs;
private boolean firstrun;
private ViewPager viewPager;
private TabLayout tabLayout;
private final int INITIAL = 1;
private final int SORT_NAME = 2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
Bundle args = new Bundle();
prefs = getSharedPreferences("ua.lanet.PipBoy", MODE_PRIVATE);
if(prefs.getBoolean("firstrun", true)){
args.putBoolean("firstrun", true);
prefs.edit().putBoolean("firstrun", false).apply();
}
else{
args.putBoolean("firstrun", false);
}
getLoaderManager().initLoader(INITIAL, args, this);
PipBoyDataHelper helper = new PipBoyDataHelper(this);
db = helper.getWritableDatabase();
}
public SQLiteDatabase getDb() {
return db;
}
#Override
public Loader onCreateLoader(int id, Bundle args) {
return new BaseInitLoader(mContext, args);
}
#Override
public void onLoadFinished(Loader loader, Object data) {
//do something with the data. Cast Object to your return type of loader
}
#Override
public void onLoaderReset(Loader loader) {
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.text:
getLoaderManager().initLoader(SORT_NAME, null, this);
break;
}
}
private class ViewPagerAdapter extends FragmentPagerAdapter{
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
}
}
So I have a custom listview. It's like Instagram layout with 1 image and bunch of buttons in each list items. So here's the problem:
I want to implement the share button. To do this, I tried to create a callback from adapter to activity. But it didn't seem to work. Here is what I have so far(I cropped out the unrelated parts):
MainActivity
public class MainActivity extends ActionBarActivity implements ListAdapter.OnShareClickedListener{
ListView main_list;
List<String> url_list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
main_list = (ListView) findViewById(R.id.listView);
ListAdapter nListAdapter = new ListAdapter(context, url_list);
main_list.setAdapter(nListAdapter);
}
#Override
public void ShareClicked(String url) {
Log.e("Test",url);
}
}
ListAdapter
public class ListAdapter extends BaseAdapter implements View.OnClickListener {
OnShareClickedListener mCallback;
Context context;
public static List<String> url_list;
public ListAdapter(Context c, List<String> list) {
this.context = c;
url_list = list;
}
public interface OnShareClickedListener {
public void ShareClicked(String url);
}
#Override
public void onClick(View v) {
mCallback.ShareClicked("Share this text.");
}
}
}
Error Log:
Attempt to invoke interface method 'void com.packagename.ListAdapter$OnShareClickedListener.ShareClicked(java.lang.String)' on a null object reference
You need to tell the adapter which implementation of the OnShareClickedListener() to use. Right now in your adapter the field mCallback is never assigned to, either you need to have a setOnSharedClickedListener() method in your adapter which you then call from your mainActivity and set it with the main activity's implementation or you need to take in the constructor.
My suggestion would be to use a setter instead of constructor. So what you need to do is this.
Your ListAdapter
public class ListAdapter extends BaseAdapter implements View.OnClickListener {
OnShareClickedListener mCallback;
Context context;
public static List<String> url_list;
public ListAdapter(Context c, List<String> list) {
this.context = c;
url_list = list;
}
public void setOnShareClickedListener(OnShareClickedListener mCallback) {
this.mCallback = mCallback;
}
public interface OnShareClickedListener {
public void ShareClicked(String url);
}
#Override
public void onClick(View v) {
mCallback.ShareClicked("Share this text.");
}
}
Your MainActivty
public class MainActivity extends ActionBarActivity implements ListAdapter.OnShareClickedListener{
ListView main_list;
List<String> url_list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
main_list = (ListView) findViewById(R.id.listView);
ListAdapter nListAdapter = new ListAdapter(this, url_list);
nListAdapter.setOnShareClickedListener(this);
main_list.setAdapter(nListAdapter);
}
#Override
public void ShareClicked(String url) {
Log.e("Test", url);
}
}
I have to parse a web page and store the content of some tag in a ListView.
Now, I have this code:
public class MainActivity extends Activity
{
private MyTask myTask;
ListView listView;
final String URL = "http://en.wikipedia.org";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.list);
myTask = new MyTask();
myTask.execute(URL);
}
class MyTask extends AsyncTask<String, Void, String>
{
#Override
protected void onPreExecute()
{
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String url = params[0];
Document doc;
Elements table = null;
try {
doc = Jsoup.connect(url).get();
table = doc.select("table").select("tbody");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return table.toString();
}
protected void onPostExecute(String result)
{
super.onPostExecute(result);
listView = (ListView) findViewById(R.id.list);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, R.layout.riga);
listView.setAdapter(adapter);
}
}
}
but the execution return always a white screen. What can I do??
I'm sure that the error is in the postExecute method but I can't see it.