edumsg.edumsg_android_app.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for edumsg.edumsg_android_app.MainActivity.java

Source

/*
 * EduMsg is made available under the OSI-approved MIT license.
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

package edumsg.edumsg_android_app;

import android.app.SearchManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar;
import android.text.InputType;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;

import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;

import net.steamcrafted.loadtoast.LoadToast;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import butterknife.Bind;
import butterknife.BindColor;
import butterknife.ButterKnife;

/**
 * Provides the home page for a user, which contains a news feed of tweets and an action bar.
 */

public class MainActivity extends MyAppCompatActivity {

    /**
     * A {@link List} of type {@link Tweet} which represents the tweets in the news feed.
     */
    private List<Tweet> tweetObjects;
    /**
     * An instance of the class {@link RVAdapter} which is a custom made RecyclerView adapter to display each tweet's view.
     */
    private RVAdapter rvAdapter;
    /**
     * An {@link ArrayList} that contains all the current logged in user's retweets' IDs. It is used to set the correct button states for previously retweeted tweets.
     */
    private ArrayList retweets;
    /**
     * An {@link ArrayList} that contains all the current logged in user's favorites' IDs.
     * It is used to set the correct button states for previously favorited tweets.
     */
    private ArrayList favorites;
    /**
     * View look-up used to reference a color in the XML colors file.
     */
    @BindColor(R.color.colorPrimary)
    int cPrimary;
    /**
     * View look-up used to reference view elements in the XML layout file.
     */
    @Bind(R.id.my_toolbar)
    Toolbar toolbar;
    /**
     * View look-up used to reference view elements in the XML layout file.
     */
    @Bind(R.id.refresh)
    SwipeRefreshLayout swipeRefreshLayout;
    /**
     * View look-up used to reference view elements in the XML layout file.
     */
    @Bind(R.id.tweets_recycler_view)
    RecyclerView recyclerView;

    /**
     *
     * The onCreate method first retrieves the sessionId and username from the parent {@link android.content.Intent},
     * which is either created from a {@link LoginFragment} or a {@link RegisterFragment}. Afterwards,
     * it configures the action bar and performs view look-ups for the action bar buttons, followed
     * by setting the onClick listeners for the action bar buttons. Finally, it initializes the
     * properties, sets the onRefresh listener for the swipe refresh layout, and calls the method
     * {@link MainActivity#getFeed()}.
     *
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sessionId = getIntent().getExtras().getString("sessionId");
        username = getIntent().getExtras().getString("username");
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        setSupportActionBar(toolbar);
        final ViewGroup actionBarLayout = (ViewGroup) getLayoutInflater().inflate(R.layout.menu_main, null);
        final ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
        actionBar.setCustomView(actionBarLayout);
        ImageButton homeButton = ButterKnife.findById(actionBarLayout, R.id.btn_home);
        final ImageButton searchButton = ButterKnife.findById(actionBarLayout, R.id.btn_search);
        ImageButton createButton = ButterKnife.findById(actionBarLayout, R.id.btn_create);
        ImageButton navButton = ButterKnife.findById(actionBarLayout, R.id.btn_nav);

        final ViewGroup searchLayout = (ViewGroup) getLayoutInflater().inflate(R.layout.menu_search, null);
        final SearchView searchView = ButterKnife.findById(searchLayout, R.id.search);
        final ImageButton backBtn = ButterKnife.findById(searchLayout, R.id.btn_back);

        homeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

        searchButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                actionBar.setCustomView(searchLayout);
                SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
                searchView.setSearchableInfo(searchManager
                        .getSearchableInfo(new ComponentName(MainActivity.this, SearchResultsActivity.class)));
                searchView.setQuery("", false);
                searchView.setIconified(false);
                searchView.setFocusable(true);
                searchView.requestFocusFromTouch();
            }
        });

        backBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                actionBar.setCustomView(actionBarLayout);
                InputMethodManager imm = (InputMethodManager) getApplicationContext()
                        .getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(
                        MainActivity.this.getWindow().getDecorView().getRootView().getWindowToken(), 0);
            }
        });

        createButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

                final EditText input = new EditText(MainActivity.this);
                input.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE);
                input.setLines(4);
                input.setSingleLine(false);
                input.setBackgroundDrawable(null);
                builder.setView(input);
                builder.setPositiveButton("Tweet", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        createTweet(input.getText().toString());
                    }
                });
                builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                });
                final AlertDialog dialog = builder.create();

                dialog.setOnShowListener(new DialogInterface.OnShowListener() {
                    @Override
                    public void onShow(DialogInterface dialogInterface) {
                        Button posBtn = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
                        posBtn.setBackgroundColor(cPrimary);
                        posBtn.setTextColor(Color.WHITE);
                        final float scale = getApplicationContext().getResources().getDisplayMetrics().density;
                        int pixels = (int) (10 * scale + 0.5f);
                        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                        layoutParams.setMargins(0, 0, pixels, 0);
                        posBtn.setLayoutParams(layoutParams);
                        Button negBtn = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
                        negBtn.setBackgroundColor(cPrimary);
                        negBtn.setTextColor(Color.WHITE);
                    }
                });
                dialog.show();
            }
        });

        navButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentManager fragmentManager = getSupportFragmentManager();
                List<Fragment> fragments = fragmentManager.getFragments();
                if (fragments != null) {
                    for (Fragment fragment : fragments) {
                        if (fragment instanceof NavigationFragment)
                            return;
                    }
                }
                NavigationFragment navigationFragment = new NavigationFragment();
                //                Bundle bundle = new_user Bundle();
                //                bundle.putInt("userId", userId);
                //                mainActivityFragment.setArguments(bundle);
                fragmentManager.beginTransaction().add(android.R.id.content, navigationFragment)
                        .addToBackStack("nav").commit();
                //                logout();
                //                launchMessages();
                //                Intent intent = new_user Intent(MainActivity.this, ProfileActivity.class);
                //                intent.putExtra("username", getUsername());
                //                intent.putExtra("name", getName());
                //                intent.putExtra("avatar_url", getAvatar_url());
                //                intent.putExtra("bio", getBio());
                //                intent.putExtra("creatorId", getUserId());
                //                intent.putExtra("userId", getUserId());
                //                startActivity(intent);
            }
        });

        recyclerView.setHasFixedSize(true);
        final float scale = getApplicationContext().getResources().getDisplayMetrics().density;
        int pixels = (int) (160 * scale + 0.5f);
        Paint paint = new Paint();
        paint.setStrokeWidth(3.0f);
        paint.setColor(Color.rgb(220, 220, 220));
        paint.setAntiAlias(true);
        recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this).paint(paint).build());
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);

        tweetObjects = new ArrayList<>();
        rvAdapter = new RVAdapter(this, tweetObjects, sessionId);
        recyclerView.setAdapter(rvAdapter);

        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                tweetObjects.clear();
                getFeed();
            }
        });

        getFeed();
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(TAG);
        }
    }

    /**
     * Creates a {@link JsonObjectRequest} with parameters supplied in a {@link Map<String, String>}.
     * Two other {@link JsonObjectRequest} are nested within the {@link com.android.volley.Response.Listener#onResponse(Object)}
     * callback method. First it retrieves the user's retweets, then their favorites, finally their
     * timeline.
     */
    private void getFeed() {
        final LoadToast loadToast = new LoadToast(this);
        final float scale = getApplicationContext().getResources().getDisplayMetrics().density;
        int pixels = (int) (56 * scale + 0.5f);
        loadToast.setTranslationY(pixels);
        if (!swipeRefreshLayout.isRefreshing()) {
            loadToast.setText("Loading...");
            loadToast.show();
        }
        Map<String, String> jsonParams2 = new HashMap<>();
        jsonParams2.put("queue", "USER");
        jsonParams2.put("method", "get_retweets");
        jsonParams2.put("session_id", sessionId + "");
        JSONObject jsonRequest2 = new JSONObject(jsonParams2);
        JsonObjectRequest jsonObjectRequest2 = new JsonObjectRequest(Request.Method.POST, requestUrl, jsonRequest2,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        try {
                            final ObjectMapper mapper = new ObjectMapper();
                            Map<String, Object> responseMap = mapper.readValue(response.toString(),
                                    new TypeReference<HashMap<String, Object>>() {
                                    });
                            retweets = (ArrayList) responseMap.get("tweet_ids");
                            Map<String, String> jsonParams = new HashMap<>();
                            jsonParams.put("queue", "USER");
                            jsonParams.put("method", "get_favorites");
                            jsonParams.put("session_id", sessionId);
                            JSONObject jsonRequest = new JSONObject(jsonParams);
                            JsonObjectRequest jsonObjectRequest3 = new JsonObjectRequest(Request.Method.POST,
                                    requestUrl, jsonRequest, new Response.Listener<JSONObject>() {
                                        @Override
                                        public void onResponse(JSONObject response) {
                                            try {
                                                Map<String, Object> responseMap = mapper.readValue(
                                                        response.toString(),
                                                        new TypeReference<HashMap<String, Object>>() {
                                                        });
                                                favorites = (ArrayList) responseMap.get("favorites");
                                                Map<String, String> jsonParams = new HashMap<>();
                                                jsonParams.put("queue", "USER");
                                                jsonParams.put("method", "timeline");
                                                jsonParams.put("session_id", sessionId);
                                                JSONObject jsonRequest = new JSONObject(jsonParams);
                                                JsonObjectRequest jsonObjectRequest4 = new JsonObjectRequest(
                                                        Request.Method.POST, requestUrl, jsonRequest,
                                                        new Response.Listener<JSONObject>() {
                                                            @Override
                                                            public void onResponse(JSONObject response) {
                                                                try {
                                                                    Map<String, Object> responseMap = mapper
                                                                            .readValue(response.toString(),
                                                                                    new TypeReference<HashMap<String, Object>>() {
                                                                                    });
                                                                    if (responseMap.get("code").equals("200")) {
                                                                        if (!swipeRefreshLayout.isRefreshing())
                                                                            loadToast.success();
                                                                        ArrayList tweetsArray = (ArrayList) responseMap
                                                                                .get("feeds");
                                                                        final Iterator iterator = tweetsArray
                                                                                .iterator();
                                                                        while (iterator.hasNext()) {
                                                                            final Map<String, Object> tweetJsonObj = mapper
                                                                                    .readValue(mapper
                                                                                            .writeValueAsString(
                                                                                                    iterator.next()),
                                                                                            new TypeReference<HashMap<String, Object>>() {
                                                                                            });
                                                                            final int tweetId = (int) tweetJsonObj
                                                                                    .get("id");
                                                                            final LinkedHashMap creatorMap = (LinkedHashMap) tweetJsonObj
                                                                                    .get("creator");
                                                                            final int creatorId = (int) creatorMap
                                                                                    .get("id");
                                                                            final String creatorUsername = (String) creatorMap
                                                                                    .get("username");
                                                                            if (creatorUsername == username)
                                                                                continue;
                                                                            String tweetText = (String) tweetJsonObj
                                                                                    .get("tweet_text");
                                                                            String avatarUrl = (String) creatorMap
                                                                                    .get("avatar_url");
                                                                            User creator = new User();
                                                                            creator.setId(creatorId);
                                                                            creator.setName((String) creatorMap
                                                                                    .get("name"));
                                                                            creator.setUsername((String) creatorMap
                                                                                    .get("username"));
                                                                            creator.setAvatar_url(avatarUrl);
                                                                            final LinkedHashMap retweeterMap = (LinkedHashMap) tweetJsonObj
                                                                                    .get("retweeter");
                                                                            final Tweet tweetObject = new Tweet(
                                                                                    tweetId, creator, tweetText);
                                                                            if (retweeterMap != null) {
                                                                                User retweeter = new User();
                                                                                retweeter.setId((int) retweeterMap
                                                                                        .get("id"));
                                                                                retweeter.setName(
                                                                                        (String) retweeterMap
                                                                                                .get("name"));
                                                                                retweeter.setUsername(
                                                                                        (String) retweeterMap
                                                                                                .get("username"));
                                                                                tweetObject.setRetweeter(retweeter);
                                                                            }
                                                                            if (avatarUrl != null
                                                                                    && !avatarUrl.equals("")) {
                                                                                tweetObject.setImgUrl(avatarUrl);
                                                                            }
                                                                            if (retweets.contains(
                                                                                    Integer.valueOf(tweetId))) {
                                                                                tweetObject.setIsRetweeted(true);
                                                                            }
                                                                            Iterator favIter = favorites.iterator();
                                                                            while (favIter.hasNext()) {
                                                                                Map<String, Object> tweetJsonObj2 = mapper
                                                                                        .readValue(mapper
                                                                                                .writeValueAsString(
                                                                                                        favIter.next()),
                                                                                                new TypeReference<HashMap<String, Object>>() {
                                                                                                });
                                                                                if (tweetId == (int) tweetJsonObj2
                                                                                        .get("id")) {
                                                                                    tweetObject
                                                                                            .setIsFavorited(true);
                                                                                    break;
                                                                                }
                                                                            }
                                                                            tweetObjects.add(tweetObject);
                                                                        }
                                                                        if (swipeRefreshLayout.isRefreshing()) {
                                                                            rvAdapter.notifyDataSetChanged();
                                                                            swipeRefreshLayout.setRefreshing(false);
                                                                        } else {
                                                                            rvAdapter.notifyItemRangeInserted(0,
                                                                                    tweetObjects.size());
                                                                        }
                                                                    }
                                                                } catch (Exception e) {
                                                                    loadToast.error();
                                                                    e.printStackTrace();
                                                                }
                                                            }
                                                        }, new Response.ErrorListener() {
                                                            @Override
                                                            public void onErrorResponse(VolleyError error) {
                                                                loadToast.error();
                                                                error.printStackTrace();
                                                            }
                                                        }) {
                                                    @Override
                                                    public Map<String, String> getHeaders()
                                                            throws AuthFailureError {
                                                        HashMap<String, String> headers = new HashMap<String, String>();
                                                        headers.put("Content-Type",
                                                                "application/json; charset=utf-8");
                                                        //headers.put("User-agent", System.getProperty("http.agent"));
                                                        return headers;
                                                    };
                                                };
                                                jsonObjectRequest4.setTag(TAG);
                                                jsonObjectRequest4.setRetryPolicy(new DefaultRetryPolicy(10000,
                                                        DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                                                        DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
                                                getVolleyRequestQueue().add(jsonObjectRequest4);
                                            } catch (Exception e) {
                                                loadToast.error();
                                                e.printStackTrace();
                                            }
                                        }
                                    }, new Response.ErrorListener() {
                                        @Override
                                        public void onErrorResponse(VolleyError error) {
                                            loadToast.error();
                                            error.printStackTrace();
                                        }
                                    }) {
                                @Override
                                public Map<String, String> getHeaders() throws AuthFailureError {
                                    HashMap<String, String> headers = new HashMap<String, String>();
                                    headers.put("Content-Type", "application/json; charset=utf-8");
                                    //headers.put("User-agent", System.getProperty("http.agent"));
                                    return headers;
                                };
                            };
                            jsonObjectRequest3.setTag(TAG);
                            jsonObjectRequest3.setRetryPolicy(
                                    new DefaultRetryPolicy(10000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                                            DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
                            getVolleyRequestQueue().add(jsonObjectRequest3);
                        } catch (Exception e) {
                            loadToast.error();
                            e.printStackTrace();
                        }
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        loadToast.error();
                        error.printStackTrace();
                    }
                }) {
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                HashMap<String, String> headers = new HashMap<String, String>();
                headers.put("Content-Type", "application/json; charset=utf-8");
                //headers.put("User-agent", System.getProperty("http.agent"));
                return headers;
            };
        };
        jsonObjectRequest2.setTag(TAG);
        jsonObjectRequest2.setRetryPolicy(new DefaultRetryPolicy(10000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
        getVolleyRequestQueue().add(jsonObjectRequest2);
    }

    /**
     * Creates a {@link JsonObjectRequest} that performs the action of creating a tweet,
     * with parameters supplied in a {@link Map<String, String>}.
     * @param tweet
     * A string containing the tweet to be created.
     */
    private void createTweet(final String tweet) {
        final LoadToast loadToast = new LoadToast(this);
        final float scale = getApplicationContext().getResources().getDisplayMetrics().density;
        int pixels = (int) (56 * scale + 0.5f);
        loadToast.setTranslationY(pixels);
        loadToast.setText("Tweeting...");
        loadToast.show();
        Map<String, String> jsonParams = new HashMap<>();
        jsonParams.put("queue", "TWEET");
        jsonParams.put("method", "tweet");
        jsonParams.put("tweet_text", tweet);
        jsonParams.put("session_id", sessionId);
        JSONObject jsonRequest = new JSONObject(jsonParams);
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, requestUrl, jsonRequest,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(final JSONObject response) {
                        final ObjectMapper mapper = new ObjectMapper();
                        try {
                            final Map<String, Object> responseMap = mapper.readValue(response.toString(),
                                    new TypeReference<HashMap<String, Object>>() {
                                    });
                            if (responseMap.get("code").equals("200")) {
                                loadToast.success();
                            }
                        } catch (Exception e) {
                            loadToast.error();
                            Log.e("JSONMapper", e.getMessage());
                        }
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError volleyError) {
                        loadToast.error();
                        if (volleyError.networkResponse != null && volleyError.networkResponse.data != null
                                && volleyError.networkResponse.statusCode == 400) {
                            try {
                                String errorJson = new String(volleyError.networkResponse.data);
                                JSONObject errorObj = new JSONObject(errorJson);
                                String error = errorObj.getString("message");
                                Log.e("Error from server", error);
                                //                        if (error.toLowerCase().contains("username"))
                                //                        {
                                //                            mUsername.setError(error);
                                //                            mUsername.requestFocus();
                                //                        }
                                //                        if (error.toLowerCase().contains("password")) {
                                //                            mPassword.setError(error);
                                //                            mPassword.requestFocus();
                                //                        }
                            } catch (JSONException e) {
                                loadToast.error();
                                Log.e("Response Error Msg", e.getMessage());
                            }
                        } else {
                            Log.e("Volley", volleyError.toString());
                        }
                    }
                }) {
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                HashMap<String, String> headers = new HashMap<String, String>();
                headers.put("Content-Type", "application/json; charset=utf-8");
                //headers.put("User-agent", System.getProperty("http.agent"));
                return headers;
            };
        };
        jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(10000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
        jsonObjectRequest.setTag(TAG);
        getVolleyRequestQueue().add(jsonObjectRequest);
    }

    public ArrayList getRetweets() {
        return retweets;
    }

    public ArrayList getFavorites() {
        return favorites;
    }

    public int getUserId() {
        return userId;
    }

    public String getUsername() {
        return username;
    }

    public String getAvatarUrl() {
        return avatarUrl;
    }

    public String getName() {
        return name;
    }

    public String getBio() {
        return bio;
    }
}